summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--Documentation/admin-guide/sysctl/net.rst8
-rw-r--r--Documentation/arm64/silicon-errata.rst3
-rw-r--r--Documentation/devicetree/bindings/net/adi,adin.yaml15
-rw-r--r--Documentation/devicetree/bindings/net/can/ctu,ctucanfd.yaml3
-rw-r--r--Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml3
-rw-r--r--Documentation/devicetree/bindings/net/marvell,orion-mdio.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml4
-rw-r--r--Documentation/networking/device_drivers/can/ctu/ctucanfd-driver.rst4
-rw-r--r--Documentation/networking/index.rst4
-rw-r--r--Documentation/process/embargoed-hardware-issues.rst7
-rw-r--r--MAINTAINERS6
-rw-r--r--Makefile2
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-asrock-romed8hm3.dts4
-rw-r--r--arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi10
-rw-r--r--arch/arm/boot/dts/aspeed-g6.dtsi10
-rw-r--r--arch/arm/boot/dts/imx6qdl-sr-som.dtsi10
-rw-r--r--arch/arm/include/asm/io.h3
-rw-r--r--arch/arm/mm/ioremap.c8
-rw-r--r--arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250-mtp.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250.dtsi4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts40
-rw-r--r--arch/arm64/include/asm/io.h4
-rw-r--r--arch/arm64/kernel/Makefile4
-rw-r--r--arch/arm64/kernel/cpu_errata.c2
-rw-r--r--arch/arm64/kernel/cpufeature.c3
-rw-r--r--arch/arm64/kernel/vdso/Makefile3
-rw-r--r--arch/arm64/kernel/vdso32/Makefile3
-rw-r--r--arch/arm64/mm/ioremap.c8
-rw-r--r--arch/powerpc/kvm/book3s_32_sr.S26
-rw-r--r--arch/x86/mm/init_64.c5
-rw-r--r--block/mq-deadline.c1
-rw-r--r--drivers/base/firmware_loader/main.c17
-rw-r--r--drivers/bcma/driver_gpio.c7
-rw-r--r--drivers/dma-buf/dma-buf.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c5
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c8
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c13
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c28
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_irq.c26
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c8
-rw-r--r--drivers/hwmon/Kconfig2
-rw-r--r--drivers/hwmon/tmp401.c11
-rw-r--r--drivers/interconnect/core.c8
-rw-r--r--drivers/net/can/Kconfig17
-rw-r--r--drivers/net/can/at91_can.c12
-rw-r--r--drivers/net/can/c_can/c_can_main.c19
-rw-r--r--drivers/net/can/ctucanfd/Kconfig6
-rw-r--r--drivers/net/can/ctucanfd/ctucanfd_base.c10
-rw-r--r--drivers/net/can/dev/Makefile2
-rw-r--r--drivers/net/can/dev/dev.c5
-rw-r--r--drivers/net/can/dev/rx-offload.c5
-rw-r--r--drivers/net/can/flexcan/flexcan-core.c7
-rw-r--r--drivers/net/can/grcan.c2
-rw-r--r--drivers/net/can/ifi_canfd/ifi_canfd.c9
-rw-r--r--drivers/net/can/janz-ican3.c2
-rw-r--r--drivers/net/can/led.c140
-rw-r--r--drivers/net/can/m_can/m_can.c35
-rw-r--r--drivers/net/can/m_can/m_can.h4
-rw-r--r--drivers/net/can/m_can/m_can_pci.c48
-rw-r--r--drivers/net/can/mscan/mscan.c2
-rw-r--r--drivers/net/can/pch_can.c2
-rw-r--r--drivers/net/can/rcar/rcar_can.c12
-rw-r--r--drivers/net/can/rcar/rcar_canfd.c11
-rw-r--r--drivers/net/can/sja1000/sja1000.c11
-rw-r--r--drivers/net/can/slcan.c4
-rw-r--r--drivers/net/can/spi/hi311x.c8
-rw-r--r--drivers/net/can/spi/mcp251x.c10
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd.h2
-rw-r--r--drivers/net/can/sun4i_can.c7
-rw-r--r--drivers/net/can/ti_hecc.c8
-rw-r--r--drivers/net/can/usb/mcba_usb.c8
-rw-r--r--drivers/net/can/usb/usb_8dev.c11
-rw-r--r--drivers/net/can/xilinx_can.c12
-rw-r--r--drivers/net/dsa/lantiq_gswip.c9
-rw-r--r--drivers/net/dsa/microchip/ksz8795.c252
-rw-r--r--drivers/net/dsa/microchip/ksz8795_spi.c35
-rw-r--r--drivers/net/dsa/microchip/ksz8863_smi.c10
-rw-r--r--drivers/net/dsa/microchip/ksz9477.c200
-rw-r--r--drivers/net/dsa/microchip/ksz9477_i2c.c30
-rw-r--r--drivers/net/dsa/microchip/ksz9477_spi.c30
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c485
-rw-r--r--drivers/net/dsa/microchip/ksz_common.h79
-rw-r--r--drivers/net/dsa/realtek/rtl8366rb.c37
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe.h3
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c6
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c2
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_main.c3
-rw-r--r--drivers/net/ethernet/dec/tulip/eeprom.c7
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip_core.c64
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c5
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c2
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.c16
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c7
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.c19
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx.h11
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c3
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_main.c31
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_rx.c3
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_tx.c3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/Kconfig1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h10
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c45
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c27
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c23
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h1
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c103
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.h40
-rw-r--r--drivers/net/ethernet/mediatek/mtk_ppe_offload.c3
-rw-r--r--drivers/net/ethernet/mediatek/mtk_sgmii.c176
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c47
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Makefile2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/alloc.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cmd.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/debugfs.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/params.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c58
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c52
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/trap.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_common.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_fs.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c39
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c28
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tx.c111
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c131
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c21
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c192
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h41
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c101
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h26
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c21
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c71
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/vport.c52
-rw-r--r--drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c2
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_main.c28
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/conntrack.c243
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/match.c51
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_main.c1
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_main.c1
-rw-r--r--drivers/net/ethernet/qlogic/qla3xxx.c3
-rw-r--r--drivers/net/ethernet/sfc/ef100_nic.c3
-rw-r--r--drivers/net/ethernet/sfc/falcon/tx.c3
-rw-r--r--drivers/net/ethernet/sfc/siena/efx_channels.h4
-rw-r--r--drivers/net/ethernet/sfc/tx_common.c3
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/enh_desc.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/norm_desc.c6
-rw-r--r--drivers/net/ethernet/sun/cassini.c4
-rw-r--r--drivers/net/ethernet/sunplus/Kconfig3
-rw-r--r--drivers/net/ethernet/sunplus/spl2sw_int.c4
-rw-r--r--drivers/net/ethernet/sunplus/spl2sw_mdio.c11
-rw-r--r--drivers/net/ethernet/synopsys/dwc-xlgmac.h3
-rw-r--r--drivers/net/ethernet/ti/am65-cpsw-qos.c13
-rw-r--r--drivers/net/hyperv/rndis_filter.c2
-rw-r--r--drivers/net/ipa/gsi.c6
-rw-r--r--drivers/net/ipa/ipa_endpoint.c13
-rw-r--r--drivers/net/ipa/ipa_interrupt.c6
-rw-r--r--drivers/net/ipa/ipa_qmi.c2
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/phy/adin.c40
-rw-r--r--drivers/net/phy/marvell.c37
-rw-r--r--drivers/net/phy/micrel.c16
-rw-r--r--drivers/net/ppp/pppoe.c1
-rw-r--r--drivers/net/usb/r8152.c33
-rw-r--r--drivers/net/veth.c1
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c6
-rw-r--r--drivers/net/wireless/Makefile2
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c13
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.c178
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.h9
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c10
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.c8
-rw-r--r--drivers/net/wireless/ath/ath11k/hal.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.c23
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c172
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.h4
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c24
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/reg.c3
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c62
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.h46
-rw-r--r--drivers/net/wireless/ath/ath11k/wow.c34
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c14
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c10
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c23
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mei/main.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c17
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/power.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c44
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c48
-rw-r--r--drivers/net/wireless/mediatek/mt76/agg-rx.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/dma.c215
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c14
-rw-r--r--drivers/net/wireless/mediatek/mt76/mcu.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mmio.c9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h50
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/beacon.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/dma.c12
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/main.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/dma.c10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/main.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mmio.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_util.c10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c201
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/dma.c61
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/init.c129
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mac.c249
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mac.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/main.c72
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.c148
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.h39
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mmio.c39
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h26
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/pci.c99
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/regs.h61
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/soc.c41
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/dma.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/init.c15
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mac.c41
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/main.c155
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.c122
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h15
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/pci.c10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/regs.h5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/usb.c62
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/tx.c53
-rw-r--r--drivers/net/wireless/microchip/wilc1000/hif.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/mon.c4
-rw-r--r--drivers/net/wireless/microchip/wilc1000/netdev.c3
-rw-r--r--drivers/net/wireless/microchip/wilc1000/sdio.c2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan.c7
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c4
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c2
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/Kconfig18
-rw-r--r--drivers/net/wireless/realtek/rtw89/Makefile9
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c11
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h14
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c5
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c23
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c12
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c3
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c30
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h3
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h22
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c229
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c18
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_table.c3714
-rw-r--r--drivers/net/wireless/silabs/wfx/bh.c6
-rw-r--r--drivers/net/wireless/silabs/wfx/data_rx.c5
-rw-r--r--drivers/net/wireless/silabs/wfx/data_tx.c3
-rw-r--r--drivers/net/wireless/silabs/wfx/hif_tx.c2
-rw-r--r--drivers/net/wireless/silabs/wfx/key.c4
-rw-r--r--drivers/net/wireless/silabs/wfx/main.c6
-rw-r--r--drivers/net/wireless/silabs/wfx/queue.c3
-rw-r--r--drivers/net/wireless/silabs/wfx/scan.c11
-rw-r--r--drivers/net/wireless/silabs/wfx/sta.c76
-rw-r--r--drivers/net/wireless/silabs/wfx/wfx.h7
-rw-r--r--drivers/net/wireless/ti/wl1251/event.c22
-rw-r--r--drivers/net/wireless/ti/wl1251/io.c20
-rw-r--r--drivers/net/wireless/ti/wl1251/tx.c15
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c10
-rw-r--r--drivers/net/wwan/t7xx/t7xx_dpmaif.c6
-rw-r--r--drivers/net/wwan/t7xx/t7xx_hif_cldma.c7
-rw-r--r--drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c6
-rw-r--r--drivers/net/wwan/t7xx/t7xx_modem_ops.c4
-rw-r--r--drivers/net/wwan/t7xx/t7xx_pci.c2
-rw-r--r--drivers/net/wwan/t7xx/t7xx_port_proxy.c3
-rw-r--r--drivers/nfc/pn533/pn533.c5
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c7
-rw-r--r--drivers/pci/controller/pci-aardvark.c48
-rw-r--r--drivers/pci/pci.c10
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c17
-rw-r--r--drivers/ptp/ptp_clockmatrix.c321
-rw-r--r--drivers/ptp/ptp_clockmatrix.h7
-rw-r--r--drivers/ptp/ptp_ocp.c62
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c3
-rw-r--r--drivers/scsi/fcoe/fcoe.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c3
-rw-r--r--drivers/slimbus/qcom-ctrl.c4
-rw-r--r--drivers/ssb/pci.c1
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3400_thermal.c48
-rw-r--r--drivers/tty/n_gsm.c20
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c29
-rw-r--r--drivers/tty/serial/digicolor-usart.c5
-rw-r--r--drivers/tty/serial/fsl_lpuart.c18
-rw-r--r--drivers/usb/class/cdc-wdm.c1
-rw-r--r--drivers/usb/gadget/function/f_uvc.c25
-rw-r--r--drivers/usb/gadget/function/uvc.h2
-rw-r--r--drivers/usb/gadget/function/uvc_v4l2.c3
-rw-r--r--drivers/usb/gadget/legacy/raw_gadget.c2
-rw-r--r--drivers/usb/host/xhci-mtk-sch.c90
-rw-r--r--drivers/usb/host/xhci-mtk.h2
-rw-r--r--drivers/usb/serial/option.c4
-rw-r--r--drivers/usb/serial/pl2303.c1
-rw-r--r--drivers/usb/serial/pl2303.h1
-rw-r--r--drivers/usb/serial/qcserial.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpci.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpci_mt6360.c26
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.c61
-rw-r--r--drivers/vhost/net.c15
-rw-r--r--drivers/video/fbdev/core/fbmem.c5
-rw-r--r--drivers/video/fbdev/core/fbsysfs.c4
-rw-r--r--drivers/video/fbdev/efifb.c9
-rw-r--r--drivers/video/fbdev/simplefb.c8
-rw-r--r--drivers/video/fbdev/vesafb.c8
-rw-r--r--fs/ceph/addr.c11
-rw-r--r--fs/ceph/file.c16
-rw-r--r--fs/gfs2/bmap.c11
-rw-r--r--fs/gfs2/file.c139
-rw-r--r--fs/io_uring.c3
-rw-r--r--fs/nfs/fs_context.c2
-rw-r--r--fs/proc/fd.c23
-rw-r--r--include/linux/audit.h2
-rw-r--r--include/linux/can/dev.h10
-rw-r--r--include/linux/can/led.h51
-rw-r--r--include/linux/ipv6.h1
-rw-r--r--include/linux/mfd/idt8a340_reg.h12
-rw-r--r--include/linux/mlx5/driver.h9
-rw-r--r--include/linux/mlx5/mlx5_ifc.h5
-rw-r--r--include/linux/netdevice.h18
-rw-r--r--include/linux/skbuff.h8
-rw-r--r--include/linux/sunrpc/clnt.h2
-rw-r--r--include/net/cfg80211.h14
-rw-r--r--include/net/inet6_hashtables.h28
-rw-r--r--include/net/inet_hashtables.h2
-rw-r--r--include/net/inet_sock.h5
-rw-r--r--include/net/inet_timewait_sock.h3
-rw-r--r--include/net/ip.h3
-rw-r--r--include/net/ipv6.h44
-rw-r--r--include/net/mac80211.h36
-rw-r--r--include/net/sock.h5
-rw-r--r--include/net/tls.h1
-rw-r--r--include/net/xfrm.h14
-rw-r--r--include/trace/events/io_uring.h2
-rw-r--r--include/trace/events/sched.h6
-rw-r--r--include/uapi/linux/can/isotp.h25
-rw-r--r--include/uapi/linux/if_link.h2
-rw-r--r--include/uapi/linux/nl80211.h2
-rw-r--r--include/uapi/linux/tls.h2
-rw-r--r--kernel/auditsc.c6
-rw-r--r--kernel/irq/irqdesc.c1
-rw-r--r--kernel/sched/core.c2
-rw-r--r--kernel/trace/fgraph.c4
-rw-r--r--kernel/trace/ftrace.c4
-rw-r--r--kernel/trace/trace_events.c8
-rw-r--r--kernel/trace/trace_osnoise.c4
-rw-r--r--kernel/trace/trace_sched_switch.c4
-rw-r--r--kernel/trace/trace_sched_wakeup.c4
-rw-r--r--lib/percpu-refcount.c1
-rw-r--r--mm/huge_memory.c7
-rw-r--r--mm/kfence/core.c10
-rw-r--r--mm/memory-failure.c15
-rw-r--r--mm/mremap.c2
-rw-r--r--net/ax25/ax25_dev.c22
-rw-r--r--net/bpf/test_run.c2
-rw-r--r--net/bridge/br_input.c7
-rw-r--r--net/can/isotp.c126
-rw-r--r--net/can/raw.c12
-rw-r--r--net/core/dev.c26
-rw-r--r--net/core/dev.h2
-rw-r--r--net/core/drop_monitor.c2
-rw-r--r--net/core/gro.c8
-rw-r--r--net/core/rtnetlink.c16
-rw-r--r--net/core/skbuff.c20
-rw-r--r--net/core/sock.c25
-rw-r--r--net/core/sysctl_net_core.c8
-rw-r--r--net/dccp/ipv4.c8
-rw-r--r--net/dccp/ipv6.c10
-rw-r--r--net/decnet/dn_route.c2
-rw-r--r--net/ipv4/inet_connection_sock.c12
-rw-r--r--net/ipv4/inet_hashtables.c10
-rw-r--r--net/ipv4/inet_timewait_sock.c58
-rw-r--r--net/ipv4/route.c23
-rw-r--r--net/ipv4/tcp_bbr.c2
-rw-r--r--net/ipv4/tcp_cubic.c4
-rw-r--r--net/ipv4/tcp_input.c10
-rw-r--r--net/ipv4/tcp_ipv4.c3
-rw-r--r--net/ipv4/tcp_output.c2
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/datagram.c6
-rw-r--r--net/ipv6/inet6_hashtables.c6
-rw-r--r--net/ipv6/ip6_offload.c56
-rw-r--r--net/ipv6/ip6_output.c22
-rw-r--r--net/ipv6/tcp_ipv6.c7
-rw-r--r--net/ipv6/udp.c13
-rw-r--r--net/key/af_key.c12
-rw-r--r--net/l2tp/l2tp_ip.c4
-rw-r--r--net/l2tp/l2tp_ip6.c8
-rw-r--r--net/mac80211/cfg.c60
-rw-r--r--net/mac80211/debugfs_netdev.c2
-rw-r--r--net/mac80211/ieee80211_i.h12
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/mlme.c117
-rw-r--r--net/mac80211/offchannel.c2
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c154
-rw-r--r--net/mac80211/rc80211_minstrel_ht.h2
-rw-r--r--net/mac80211/scan.c20
-rw-r--r--net/mac80211/status.c91
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/mac80211/util.c40
-rw-r--r--net/mac80211/wpa.c103
-rw-r--r--net/mptcp/options.c37
-rw-r--r--net/mptcp/pm.c14
-rw-r--r--net/mptcp/protocol.c28
-rw-r--r--net/mptcp/protocol.h33
-rw-r--r--net/mptcp/sockopt.c15
-rw-r--r--net/mptcp/subflow.c50
-rw-r--r--net/netfilter/nf_flow_table_core.c60
-rw-r--r--net/netfilter/nf_flow_table_ip.c19
-rw-r--r--net/netfilter/nf_tables_api.c11
-rw-r--r--net/netfilter/nft_flow_offload.c28
-rw-r--r--net/nfc/nci/data.c2
-rw-r--r--net/nfc/nci/hci.c4
-rw-r--r--net/sched/act_pedit.c4
-rw-r--r--net/sched/em_meta.c7
-rw-r--r--net/sctp/input.c4
-rw-r--r--net/sctp/output.c3
-rw-r--r--net/smc/af_smc.c50
-rw-r--r--net/smc/smc_ib.c1
-rw-r--r--net/smc/smc_tx.c17
-rw-r--r--net/smc/smc_wr.c5
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_upcall.c3
-rw-r--r--net/sunrpc/clnt.c36
-rw-r--r--net/tls/tls_device.c53
-rw-r--r--net/tls/tls_main.c55
-rw-r--r--net/tls/tls_sw.c4
-rw-r--r--net/wireless/chan.c93
-rw-r--r--net/wireless/core.h14
-rw-r--r--net/wireless/ibss.c4
-rw-r--r--net/wireless/nl80211.c416
-rw-r--r--net/wireless/reg.c4
-rw-r--r--net/xfrm/xfrm_policy.c2
-rw-r--r--samples/trace_events/trace_custom_sched.h6
-rw-r--r--security/selinux/ss/hashtab.c3
-rw-r--r--sound/isa/wavefront/wavefront_synth.c3
-rw-r--r--sound/pci/hda/patch_realtek.c71
-rw-r--r--sound/usb/quirks-table.h9
-rw-r--r--sound/usb/quirks.c2
-rw-r--r--tools/include/uapi/linux/if_link.h2
-rw-r--r--tools/include/uapi/linux/kvm.h10
-rw-r--r--tools/perf/bench/numa.c2
-rwxr-xr-xtools/perf/tests/shell/test_arm_coresight.sh1
-rwxr-xr-xtools/testing/selftests/drivers/net/netdevsim/hw_stats_l3.sh4
-rw-r--r--tools/testing/selftests/net/forwarding/Makefile2
-rwxr-xr-xtools/testing/selftests/net/mptcp/mptcp_join.sh59
-rw-r--r--tools/testing/selftests/vm/Makefile10
503 files changed, 9757 insertions, 5804 deletions
diff --git a/.mailmap b/.mailmap
index ecd51ee5fa0c..0b04aa20c431 100644
--- a/.mailmap
+++ b/.mailmap
@@ -251,6 +251,7 @@ Mark Yao <markyao0591@gmail.com> <mark.yao@rock-chips.com>
Martin Kepplinger <martink@posteo.de> <martin.kepplinger@ginzinger.com>
Martin Kepplinger <martink@posteo.de> <martin.kepplinger@puri.sm>
Martin Kepplinger <martink@posteo.de> <martin.kepplinger@theobroma-systems.com>
+Martyna Szapar-Mudlaw <martyna.szapar-mudlaw@linux.intel.com> <martyna.szapar-mudlaw@intel.com>
Mathieu Othacehe <m.othacehe@gmail.com>
Matthew Wilcox <willy@infradead.org> <matthew.r.wilcox@intel.com>
Matthew Wilcox <willy@infradead.org> <matthew@wil.cx>
diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst
index f86b5e1623c6..fa4dcdb283cf 100644
--- a/Documentation/admin-guide/sysctl/net.rst
+++ b/Documentation/admin-guide/sysctl/net.rst
@@ -322,6 +322,14 @@ a leaked reference faster. A larger value may be useful to prevent false
warnings on slow/loaded systems.
Default value is 10, minimum 1, maximum 3600.
+skb_defer_max
+-------------
+
+Max size (in skbs) of the per-cpu list of skbs being freed
+by the cpu which allocated them. Used by TCP stack so far.
+
+Default: 64
+
optmem_max
----------
diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst
index 466cb9e89047..d27db84d585e 100644
--- a/Documentation/arm64/silicon-errata.rst
+++ b/Documentation/arm64/silicon-errata.rst
@@ -189,6 +189,9 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| Qualcomm Tech. | Kryo4xx Silver | N/A | ARM64_ERRATUM_1024718 |
+----------------+-----------------+-----------------+-----------------------------+
+| Qualcomm Tech. | Kryo4xx Gold | N/A | ARM64_ERRATUM_1286807 |
++----------------+-----------------+-----------------+-----------------------------+
+
+----------------+-----------------+-----------------+-----------------------------+
| Fujitsu | A64FX | E#010001 | FUJITSU_ERRATUM_010001 |
+----------------+-----------------+-----------------+-----------------------------+
diff --git a/Documentation/devicetree/bindings/net/adi,adin.yaml b/Documentation/devicetree/bindings/net/adi,adin.yaml
index 1129f2b58e98..77750df0c2c4 100644
--- a/Documentation/devicetree/bindings/net/adi,adin.yaml
+++ b/Documentation/devicetree/bindings/net/adi,adin.yaml
@@ -36,6 +36,21 @@ properties:
enum: [ 4, 8, 12, 16, 20, 24 ]
default: 8
+ adi,phy-output-clock:
+ description: Select clock output on GP_CLK pin. Two clocks are available:
+ A 25MHz reference and a free-running 125MHz.
+ The phy can alternatively automatically switch between the reference and
+ the 125MHz clocks based on its internal state.
+ $ref: /schemas/types.yaml#/definitions/string
+ enum:
+ - 25mhz-reference
+ - 125mhz-free-running
+ - adaptive-free-running
+
+ adi,phy-output-reference-clock:
+ description: Enable 25MHz reference clock output on CLK25_REF pin.
+ type: boolean
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/net/can/ctu,ctucanfd.yaml b/Documentation/devicetree/bindings/net/can/ctu,ctucanfd.yaml
index fb34d971dcb3..4635cb96fc64 100644
--- a/Documentation/devicetree/bindings/net/can/ctu,ctucanfd.yaml
+++ b/Documentation/devicetree/bindings/net/can/ctu,ctucanfd.yaml
@@ -25,6 +25,9 @@ maintainers:
- Ondrej Ille <ondrej.ille@gmail.com>
- Martin Jerabek <martin.jerabek01@gmail.com>
+allOf:
+ - $ref: can-controller.yaml#
+
properties:
compatible:
oneOf:
diff --git a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
index 9fc137fafed9..6f71fc96bc4e 100644
--- a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
+++ b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml
@@ -88,6 +88,7 @@ required:
- compatible
- reg
- interrupts
+ - interrupt-names
- clocks
- clock-names
- power-domains
@@ -136,7 +137,6 @@ then:
- const: rstc_n
required:
- - interrupt-names
- reset-names
else:
properties:
@@ -167,6 +167,7 @@ examples:
reg = <0xe66c0000 0x8000>;
interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch_int", "g_int";
clocks = <&cpg CPG_MOD 914>,
<&cpg CPG_CORE R8A7795_CLK_CANFD>,
<&can_clk>;
diff --git a/Documentation/devicetree/bindings/net/marvell,orion-mdio.yaml b/Documentation/devicetree/bindings/net/marvell,orion-mdio.yaml
index fe3a3412f093..d2906b4a0f59 100644
--- a/Documentation/devicetree/bindings/net/marvell,orion-mdio.yaml
+++ b/Documentation/devicetree/bindings/net/marvell,orion-mdio.yaml
@@ -39,7 +39,7 @@ required:
- compatible
- reg
-unevaluatedProperties: true
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
index 57b68d6c7c70..3666ac5b6518 100644
--- a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
@@ -33,7 +33,7 @@ patternProperties:
$ref: "/schemas/types.yaml#/definitions/string"
enum: [ ADC0, ADC1, ADC10, ADC11, ADC12, ADC13, ADC14, ADC15, ADC2,
ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, EMMC, ESPI, ESPIALT,
- FSI1, FSI2, FWSPIABR, FWSPID, FWSPIWP, GPIT0, GPIT1, GPIT2, GPIT3,
+ FSI1, FSI2, FWQSPI, FWSPIABR, FWSPID, FWSPIWP, GPIT0, GPIT1, GPIT2, GPIT3,
GPIT4, GPIT5, GPIT6, GPIT7, GPIU0, GPIU1, GPIU2, GPIU3, GPIU4, GPIU5,
GPIU6, GPIU7, I2C1, I2C10, I2C11, I2C12, I2C13, I2C14, I2C15, I2C16,
I2C2, I2C3, I2C4, I2C5, I2C6, I2C7, I2C8, I2C9, I3C3, I3C4, I3C5,
@@ -58,7 +58,7 @@ patternProperties:
$ref: "/schemas/types.yaml#/definitions/string"
enum: [ ADC0, ADC1, ADC10, ADC11, ADC12, ADC13, ADC14, ADC15, ADC2,
ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, EMMCG1, EMMCG4,
- EMMCG8, ESPI, ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID, FWQSPID, FWSPIWP,
+ EMMCG8, ESPI, ESPIALT, FSI1, FSI2, FWQSPI, FWSPIABR, FWSPID, FWSPIWP,
GPIT0, GPIT1, GPIT2, GPIT3, GPIT4, GPIT5, GPIT6, GPIT7, GPIU0, GPIU1,
GPIU2, GPIU3, GPIU4, GPIU5, GPIU6, GPIU7, HVI3C3, HVI3C4, I2C1, I2C10,
I2C11, I2C12, I2C13, I2C14, I2C15, I2C16, I2C2, I2C3, I2C4, I2C5,
diff --git a/Documentation/networking/device_drivers/can/ctu/ctucanfd-driver.rst b/Documentation/networking/device_drivers/can/ctu/ctucanfd-driver.rst
index 2fde5551e756..40c92ea272af 100644
--- a/Documentation/networking/device_drivers/can/ctu/ctucanfd-driver.rst
+++ b/Documentation/networking/device_drivers/can/ctu/ctucanfd-driver.rst
@@ -72,7 +72,7 @@ it is reachable (on which bus it resides) and its configuration –
registers address, interrupts and so on. An example of such a device
tree is given in .
-.. code:: raw
+::
/ {
/* ... */
@@ -451,7 +451,7 @@ the FIFO is maintained, together with priority rotation, is depicted in
|
-.. figure:: fsm_txt_buffer_user.svg
+.. kernel-figure:: fsm_txt_buffer_user.svg
TX Buffer states with possible transitions
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst
index a1c271fe484e..03b215bddde8 100644
--- a/Documentation/networking/index.rst
+++ b/Documentation/networking/index.rst
@@ -1,5 +1,5 @@
-Linux Networking Documentation
-==============================
+Networking
+==========
Refer to :ref:`netdev-FAQ` for a guide on netdev development process specifics.
diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst
index 6f8f36e10e8b..95999302d279 100644
--- a/Documentation/process/embargoed-hardware-issues.rst
+++ b/Documentation/process/embargoed-hardware-issues.rst
@@ -244,10 +244,11 @@ disclosure of a particular issue, unless requested by a response team or by
an involved disclosed party. The current ambassadors list:
============= ========================================================
- ARM Grant Likely <grant.likely@arm.com>
AMD Tom Lendacky <tom.lendacky@amd.com>
- IBM Z Christian Borntraeger <borntraeger@de.ibm.com>
- IBM Power Anton Blanchard <anton@linux.ibm.com>
+ Ampere Darren Hart <darren@os.amperecomputing.com>
+ ARM Catalin Marinas <catalin.marinas@arm.com>
+ IBM Power Anton Blanchard <anton@linux.ibm.com>
+ IBM Z Christian Borntraeger <borntraeger@de.ibm.com>
Intel Tony Luck <tony.luck@intel.com>
Qualcomm Trilok Soni <tsoni@codeaurora.org>
diff --git a/MAINTAINERS b/MAINTAINERS
index 69b597aa4bc7..234380c959c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4376,7 +4376,6 @@ F: drivers/net/can/
F: drivers/phy/phy-can-transceiver.c
F: include/linux/can/bittiming.h
F: include/linux/can/dev.h
-F: include/linux/can/led.h
F: include/linux/can/length.h
F: include/linux/can/platform/
F: include/linux/can/rx-offload.h
@@ -5442,6 +5441,7 @@ F: net/ax25/sysctl_net_ax25.c
DATA ACCESS MONITOR
M: SeongJae Park <sj@kernel.org>
+L: damon@lists.linux.dev
L: linux-mm@kvack.org
S: Maintained
F: Documentation/ABI/testing/sysfs-kernel-mm-damon
@@ -14399,7 +14399,6 @@ F: arch/arm/*omap*/*pm*
F: drivers/cpufreq/omap-cpufreq.c
OMAP POWERDOMAIN SOC ADAPTATION LAYER SUPPORT
-M: Rajendra Nayak <rnayak@codeaurora.org>
M: Paul Walmsley <paul@pwsan.com>
L: linux-omap@vger.kernel.org
S: Maintained
@@ -15502,7 +15501,8 @@ F: tools/perf/
PERFORMANCE EVENTS TOOLING ARM64
R: John Garry <john.garry@huawei.com>
R: Will Deacon <will@kernel.org>
-R: Mathieu Poirier <mathieu.poirier@linaro.org>
+R: James Clark <james.clark@arm.com>
+R: Mike Leach <mike.leach@linaro.org>
R: Leo Yan <leo.yan@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported
diff --git a/Makefile b/Makefile
index 2284d1ca2503..5033c0577c6d 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
VERSION = 5
PATCHLEVEL = 18
SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
NAME = Superb Owl
# *DOCUMENTATION*
diff --git a/arch/arm/boot/dts/aspeed-bmc-asrock-romed8hm3.dts b/arch/arm/boot/dts/aspeed-bmc-asrock-romed8hm3.dts
index e71ccfd1df63..ff4c07c69af1 100644
--- a/arch/arm/boot/dts/aspeed-bmc-asrock-romed8hm3.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-asrock-romed8hm3.dts
@@ -100,12 +100,14 @@
lm25066@40 {
compatible = "lm25066";
reg = <0x40>;
+ shunt-resistor-micro-ohms = <1000>;
};
/* 12VSB PMIC */
lm25066@41 {
compatible = "lm25066";
reg = <0x41>;
+ shunt-resistor-micro-ohms = <10000>;
};
};
@@ -196,7 +198,7 @@
gpio-line-names =
/* A */ "LOCATORLED_STATUS_N", "BMC_MAC2_INTB", "NMI_BTN_N", "BMC_NMI",
"", "", "", "",
- /* B */ "DDR_MEM_TEMP", "", "", "", "", "", "", "",
+ /* B */ "POST_COMPLETE_N", "", "", "", "", "", "", "",
/* C */ "", "", "", "", "PCIE_HP_SEL_N", "PCIE_SATA_SEL_N", "LOCATORBTN", "",
/* D */ "BMC_PSIN", "BMC_PSOUT", "BMC_RESETCON", "RESETCON",
"", "", "", "PSU_FAN_FAIL_N",
diff --git a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
index e4775bbceecc..7cd4f075e325 100644
--- a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
@@ -117,9 +117,9 @@
groups = "FWSPID";
};
- pinctrl_fwqspid_default: fwqspid_default {
- function = "FWSPID";
- groups = "FWQSPID";
+ pinctrl_fwqspi_default: fwqspi_default {
+ function = "FWQSPI";
+ groups = "FWQSPI";
};
pinctrl_fwspiwp_default: fwspiwp_default {
@@ -653,12 +653,12 @@
};
pinctrl_qspi1_default: qspi1_default {
- function = "QSPI1";
+ function = "SPI1";
groups = "QSPI1";
};
pinctrl_qspi2_default: qspi2_default {
- function = "QSPI2";
+ function = "SPI2";
groups = "QSPI2";
};
diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
index 6aa1fd5c9359..3c1011678ce6 100644
--- a/arch/arm/boot/dts/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6.dtsi
@@ -393,6 +393,16 @@
reg = <0x1e6f2000 0x1000>;
};
+ video: video@1e700000 {
+ compatible = "aspeed,ast2600-video-engine";
+ reg = <0x1e700000 0x1000>;
+ clocks = <&syscon ASPEED_CLK_GATE_VCLK>,
+ <&syscon ASPEED_CLK_GATE_ECLK>;
+ clock-names = "vclk", "eclk";
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
gpio0: gpio@1e780000 {
#gpio-cells = <2>;
gpio-controller;
diff --git a/arch/arm/boot/dts/imx6qdl-sr-som.dtsi b/arch/arm/boot/dts/imx6qdl-sr-som.dtsi
index f86efd0ccc40..ce543e325cd3 100644
--- a/arch/arm/boot/dts/imx6qdl-sr-som.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sr-som.dtsi
@@ -83,6 +83,16 @@
qca,clk-out-frequency = <125000000>;
qca,smarteee-tw-us-1g = <24>;
};
+
+ /*
+ * ADIN1300 (som rev 1.9 or later) is always at address 1. It
+ * will be enabled automatically by U-Boot if detected.
+ */
+ ethernet-phy@1 {
+ reg = <1>;
+ adi,phy-output-clock = "125mhz-free-running";
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 0c70eb688a00..2a0739a2350b 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -440,6 +440,9 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
+ unsigned long flags);
+#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap
#endif
/*
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index aa08bcb72db9..290702328a33 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -493,3 +493,11 @@ void __init early_ioremap_init(void)
{
early_ioremap_setup();
}
+
+bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
+ unsigned long flags)
+{
+ unsigned long pfn = PHYS_PFN(offset);
+
+ return memblock_is_map_memory(pfn);
+}
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
index 1cee26479bfe..98c9a3265446 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
@@ -303,7 +303,7 @@
/* switch nodes are enabled by U-Boot if modules are present */
switch0@10 {
compatible = "marvell,mv88e6190";
- reg = <0x10 0>;
+ reg = <0x10>;
dsa,member = <0 0>;
interrupt-parent = <&moxtet>;
interrupts = <MOXTET_IRQ_PERIDOT(0)>;
@@ -428,7 +428,7 @@
switch0@2 {
compatible = "marvell,mv88e6085";
- reg = <0x2 0>;
+ reg = <0x2>;
dsa,member = <0 0>;
interrupt-parent = <&moxtet>;
interrupts = <MOXTET_IRQ_TOPAZ>;
@@ -495,7 +495,7 @@
switch1@11 {
compatible = "marvell,mv88e6190";
- reg = <0x11 0>;
+ reg = <0x11>;
dsa,member = <0 1>;
interrupt-parent = <&moxtet>;
interrupts = <MOXTET_IRQ_PERIDOT(1)>;
@@ -620,7 +620,7 @@
switch1@2 {
compatible = "marvell,mv88e6085";
- reg = <0x2 0>;
+ reg = <0x2>;
dsa,member = <0 1>;
interrupt-parent = <&moxtet>;
interrupts = <MOXTET_IRQ_TOPAZ>;
@@ -687,7 +687,7 @@
switch2@12 {
compatible = "marvell,mv88e6190";
- reg = <0x12 0>;
+ reg = <0x12>;
dsa,member = <0 2>;
interrupt-parent = <&moxtet>;
interrupts = <MOXTET_IRQ_PERIDOT(2)>;
@@ -803,7 +803,7 @@
switch2@2 {
compatible = "marvell,mv88e6085";
- reg = <0x2 0>;
+ reg = <0x2>;
dsa,member = <0 2>;
interrupt-parent = <&moxtet>;
interrupts = <MOXTET_IRQ_TOPAZ>;
diff --git a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
index fb99cc2827c7..7ab3627cc347 100644
--- a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
@@ -622,6 +622,10 @@
status = "okay";
};
+&rxmacro {
+ status = "okay";
+};
+
&slpi {
status = "okay";
firmware-name = "qcom/sm8250/slpi.mbn";
@@ -773,6 +777,8 @@
};
&swr1 {
+ status = "okay";
+
wcd_rx: wcd9380-rx@0,4 {
compatible = "sdw20217010d00";
reg = <0 4>;
@@ -781,6 +787,8 @@
};
&swr2 {
+ status = "okay";
+
wcd_tx: wcd9380-tx@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
@@ -819,6 +827,10 @@
};
};
+&txmacro {
+ status = "okay";
+};
+
&uart12 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index af8f22636436..1304b86af1a0 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -2255,6 +2255,7 @@
pinctrl-0 = <&rx_swr_active>;
compatible = "qcom,sm8250-lpass-rx-macro";
reg = <0 0x3200000 0 0x1000>;
+ status = "disabled";
clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
@@ -2273,6 +2274,7 @@
swr1: soundwire-controller@3210000 {
reg = <0 0x3210000 0 0x2000>;
compatible = "qcom,soundwire-v1.5.1";
+ status = "disabled";
interrupts = <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rxmacro>;
clock-names = "iface";
@@ -2300,6 +2302,7 @@
pinctrl-0 = <&tx_swr_active>;
compatible = "qcom,sm8250-lpass-tx-macro";
reg = <0 0x3220000 0 0x1000>;
+ status = "disabled";
clocks = <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
@@ -2323,6 +2326,7 @@
compatible = "qcom,soundwire-v1.5.1";
interrupts-extended = <&intc GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "core";
+ status = "disabled";
clocks = <&txmacro>;
clock-names = "iface";
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
index a01886b467ed..067fe4a6b178 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
@@ -16,6 +16,7 @@
aliases {
ethernet0 = &gmac0;
+ ethernet1 = &gmac1;
mmc0 = &sdmmc0;
mmc1 = &sdhci;
};
@@ -78,7 +79,6 @@
assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>;
assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>, <&cru CLK_MAC0_2TOP>;
clock_in_out = "input";
- phy-handle = <&rgmii_phy0>;
phy-mode = "rgmii";
pinctrl-names = "default";
pinctrl-0 = <&gmac0_miim
@@ -90,8 +90,38 @@
snps,reset-active-low;
/* Reset time is 20ms, 100ms for rtl8211f */
snps,reset-delays-us = <0 20000 100000>;
+ tx_delay = <0x4f>;
+ rx_delay = <0x0f>;
+ status = "okay";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ pause;
+ };
+};
+
+&gmac1 {
+ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
+ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru CLK_MAC1_2TOP>;
+ clock_in_out = "output";
+ phy-handle = <&rgmii_phy1>;
+ phy-mode = "rgmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1m1_miim
+ &gmac1m1_tx_bus2
+ &gmac1m1_rx_bus2
+ &gmac1m1_rgmii_clk
+ &gmac1m1_rgmii_bus>;
+
+ snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ /* Reset time is 20ms, 100ms for rtl8211f */
+ snps,reset-delays-us = <0 20000 100000>;
+
tx_delay = <0x3c>;
rx_delay = <0x2f>;
+
status = "okay";
};
@@ -315,8 +345,8 @@
status = "disabled";
};
-&mdio0 {
- rgmii_phy0: ethernet-phy@0 {
+&mdio1 {
+ rgmii_phy1: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0x0>;
};
@@ -345,9 +375,9 @@
pmuio2-supply = <&vcc3v3_pmu>;
vccio1-supply = <&vccio_acodec>;
vccio3-supply = <&vccio_sd>;
- vccio4-supply = <&vcc_1v8>;
+ vccio4-supply = <&vcc_3v3>;
vccio5-supply = <&vcc_3v3>;
- vccio6-supply = <&vcc_3v3>;
+ vccio6-supply = <&vcc_1v8>;
vccio7-supply = <&vcc_3v3>;
status = "okay";
};
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 7fd836bea7eb..3995652daf81 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -192,4 +192,8 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
+ unsigned long flags);
+#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap
+
#endif /* __ASM_IO_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 986837d7ec82..fa7981d0d917 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -75,6 +75,10 @@ obj-$(CONFIG_ARM64_MTE) += mte.o
obj-y += vdso-wrap.o
obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o
+# Force dependency (vdso*-wrap.S includes vdso.so through incbin)
+$(obj)/vdso-wrap.o: $(obj)/vdso/vdso.so
+$(obj)/vdso32-wrap.o: $(obj)/vdso32/vdso.so
+
obj-y += probes/
head-y := head.o
extra-y += $(head-y) vmlinux.lds
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 4c9b5b4b7a0b..a0f3d0aaa3c5 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -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),
},
#endif
{},
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d72c4b4d389c..2cb9cc9e0eff 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -654,7 +654,6 @@ static const struct __ftr_reg_entry {
ARM64_FTR_REG(SYS_ID_AA64ISAR0_EL1, ftr_id_aa64isar0),
ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64ISAR1_EL1, ftr_id_aa64isar1,
&id_aa64isar1_override),
- ARM64_FTR_REG(SYS_ID_AA64ISAR2_EL1, ftr_id_aa64isar2),
ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64ISAR2_EL1, ftr_id_aa64isar2,
&id_aa64isar2_override),
@@ -810,7 +809,7 @@ static void __init sort_ftr_regs(void)
* to sys_id for subsequent binary search in get_arm64_ftr_reg()
* to work correctly.
*/
- BUG_ON(arm64_ftr_regs[i].sys_id < arm64_ftr_regs[i - 1].sys_id);
+ BUG_ON(arm64_ftr_regs[i].sys_id <= arm64_ftr_regs[i - 1].sys_id);
}
}
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 172452f79e46..ac1964ebed1e 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -52,9 +52,6 @@ GCOV_PROFILE := n
targets += vdso.lds
CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
-# Force dependency (incbin is bad)
-$(obj)/vdso.o : $(obj)/vdso.so
-
# Link rule for the .so file, .lds has to be first
$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
$(call if_changed,vdsold_and_vdso_check)
diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile
index ed181bedbffc..05ba1aae1b6f 100644
--- a/arch/arm64/kernel/vdso32/Makefile
+++ b/arch/arm64/kernel/vdso32/Makefile
@@ -131,9 +131,6 @@ obj-vdso := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso)
targets += vdso.lds
CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
-# Force dependency (vdso.s includes vdso.so through incbin)
-$(obj)/vdso.o: $(obj)/vdso.so
-
include/generated/vdso32-offsets.h: $(obj)/vdso.so.dbg FORCE
$(call if_changed,vdsosym)
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
index b7c81dacabf0..b21f91cd830d 100644
--- a/arch/arm64/mm/ioremap.c
+++ b/arch/arm64/mm/ioremap.c
@@ -99,3 +99,11 @@ void __init early_ioremap_init(void)
{
early_ioremap_setup();
}
+
+bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
+ unsigned long flags)
+{
+ unsigned long pfn = PHYS_PFN(offset);
+
+ return pfn_is_map_memory(pfn);
+}
diff --git a/arch/powerpc/kvm/book3s_32_sr.S b/arch/powerpc/kvm/book3s_32_sr.S
index e3ab9df6cf19..6cfcd20d4668 100644
--- a/arch/powerpc/kvm/book3s_32_sr.S
+++ b/arch/powerpc/kvm/book3s_32_sr.S
@@ -122,11 +122,27 @@
/* 0x0 - 0xb */
- /* 'current->mm' needs to be in r4 */
- tophys(r4, r2)
- lwz r4, MM(r4)
- tophys(r4, r4)
- /* This only clobbers r0, r3, r4 and r5 */
+ /* switch_mmu_context() needs paging, let's enable it */
+ mfmsr r9
+ ori r11, r9, MSR_DR
+ mtmsr r11
+ sync
+
+ /* switch_mmu_context() clobbers r12, rescue it */
+ SAVE_GPR(12, r1)
+
+ /* Calling switch_mmu_context(<inv>, current->mm, <inv>); */
+ lwz r4, MM(r2)
bl switch_mmu_context
+ /* restore r12 */
+ REST_GPR(12, r1)
+
+ /* Disable paging again */
+ mfmsr r9
+ li r6, MSR_DR
+ andc r9, r9, r6
+ mtmsr r9
+ sync
+
.endm
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 96d34ebb20a9..e2942335d143 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -902,6 +902,8 @@ static void __meminit vmemmap_use_sub_pmd(unsigned long start, unsigned long end
static void __meminit vmemmap_use_new_sub_pmd(unsigned long start, unsigned long end)
{
+ const unsigned long page = ALIGN_DOWN(start, PMD_SIZE);
+
vmemmap_flush_unused_pmd();
/*
@@ -914,8 +916,7 @@ static void __meminit vmemmap_use_new_sub_pmd(unsigned long start, unsigned long
* Mark with PAGE_UNUSED the unused parts of the new memmap range
*/
if (!IS_ALIGNED(start, PMD_SIZE))
- memset((void *)start, PAGE_UNUSED,
- start - ALIGN_DOWN(start, PMD_SIZE));
+ memset((void *)page, PAGE_UNUSED, start - page);
/*
* We want to avoid memset(PAGE_UNUSED) when populating the vmemmap of
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index 3ed5eaf3446a..6ed602b2f80a 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -742,6 +742,7 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
if (at_head) {
list_add(&rq->queuelist, &per_prio->dispatch);
+ rq->fifo_time = jiffies;
} else {
deadline_add_rq_rb(per_prio, rq);
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 94d1789a233e..406a907a4cae 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -735,6 +735,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
size_t offset, u32 opt_flags)
{
struct firmware *fw = NULL;
+ struct cred *kern_cred = NULL;
+ const struct cred *old_cred;
bool nondirect = false;
int ret;
@@ -751,6 +753,18 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
if (ret <= 0) /* error or already assigned */
goto out;
+ /*
+ * We are about to try to access the firmware file. Because we may have been
+ * called by a driver when serving an unrelated request from userland, we use
+ * the kernel credentials to read the file.
+ */
+ kern_cred = prepare_kernel_cred(NULL);
+ if (!kern_cred) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ old_cred = override_creds(kern_cred);
+
ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
/* Only full reads can support decompression, platform, and sysfs. */
@@ -776,6 +790,9 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
} else
ret = assign_fw(fw, device);
+ revert_creds(old_cred);
+ put_cred(kern_cred);
+
out:
if (ret < 0) {
fw_abort_batch_reqs(fw);
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 1e74ec1c7f23..fac8ff983aec 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -11,6 +11,8 @@
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/export.h>
+#include <linux/property.h>
+
#include <linux/bcma/bcma.h>
#include "bcma_private.h"
@@ -182,9 +184,8 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
chip->direction_input = bcma_gpio_direction_input;
chip->direction_output = bcma_gpio_direction_output;
chip->parent = bus->dev;
-#if IS_BUILTIN(CONFIG_OF)
- chip->of_node = cc->core->dev.of_node;
-#endif
+ chip->fwnode = dev_fwnode(&cc->core->dev);
+
switch (bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM4707:
case BCMA_CHIP_ID_BCM5357:
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index df23239b04fc..b1e25ae98302 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -543,10 +543,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
file->f_mode |= FMODE_LSEEK;
dmabuf->file = file;
- ret = dma_buf_stats_setup(dmabuf);
- if (ret)
- goto err_sysfs;
-
mutex_init(&dmabuf->lock);
INIT_LIST_HEAD(&dmabuf->attachments);
@@ -554,6 +550,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
list_add(&dmabuf->list_node, &db_list.head);
mutex_unlock(&db_list.lock);
+ ret = dma_buf_stats_setup(dmabuf);
+ if (ret)
+ goto err_sysfs;
+
return dmabuf;
err_sysfs:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index 8f0e6d93bb9c..c317078d1afd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -296,6 +296,7 @@ static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
{
struct amdgpu_device *adev = ctx->adev;
enum amd_dpm_forced_level level;
+ u32 current_stable_pstate;
int r;
mutex_lock(&adev->pm.stable_pstate_ctx_lock);
@@ -304,6 +305,10 @@ static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
goto done;
}
+ r = amdgpu_ctx_get_stable_pstate(ctx, &current_stable_pstate);
+ if (r || (stable_pstate == current_stable_pstate))
+ goto done;
+
switch (stable_pstate) {
case AMDGPU_CTX_STABLE_PSTATE_NONE:
level = AMD_DPM_FORCED_LEVEL_AUTO;
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 039b90cdc3bc..45f0188c4273 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -81,6 +81,10 @@
#include "mxgpu_vi.h"
#include "amdgpu_dm.h"
+#if IS_ENABLED(CONFIG_X86)
+#include <asm/intel-family.h>
+#endif
+
#define ixPCIE_LC_L1_PM_SUBSTATE 0x100100C6
#define PCIE_LC_L1_PM_SUBSTATE__LC_L1_SUBSTATES_OVERRIDE_EN_MASK 0x00000001L
#define PCIE_LC_L1_PM_SUBSTATE__LC_PCI_PM_L1_2_OVERRIDE_MASK 0x00000002L
@@ -1134,13 +1138,24 @@ static void vi_enable_aspm(struct amdgpu_device *adev)
WREG32_PCIE(ixPCIE_LC_CNTL, data);
}
+static bool aspm_support_quirk_check(void)
+{
+#if IS_ENABLED(CONFIG_X86)
+ struct cpuinfo_x86 *c = &cpu_data(0);
+
+ return !(c->x86 == 6 && c->x86_model == INTEL_FAM6_ALDERLAKE);
+#else
+ return true;
+#endif
+}
+
static void vi_program_aspm(struct amdgpu_device *adev)
{
u32 data, data1, orig;
bool bL1SS = false;
bool bClkReqSupport = true;
- if (!amdgpu_device_should_use_aspm(adev))
+ if (!amdgpu_device_should_use_aspm(adev) || !aspm_support_quirk_check())
return;
if (adev->flags & AMD_IS_APU ||
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
index d7559e5a99ce..e708f07fe75a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
@@ -153,9 +153,4 @@ void dcn31_hw_sequencer_construct(struct dc *dc)
dc->hwss.init_hw = dcn20_fpga_init_hw;
dc->hwseq->funcs.init_pipes = NULL;
}
- if (dc->debug.disable_z10) {
- /*hw not support z10 or sw disable it*/
- dc->hwss.z10_restore = NULL;
- dc->hwss.z10_save_init = NULL;
- }
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index f1544755d8b4..f10a0256413e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -1351,14 +1351,8 @@ static int smu_disable_dpms(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
int ret = 0;
- /*
- * TODO: (adev->in_suspend && !adev->in_s0ix) is added to pair
- * the workaround which always reset the asic in suspend.
- * It's likely that workaround will be dropped in the future.
- * Then the change here should be dropped together.
- */
bool use_baco = !smu->is_apu &&
- (((amdgpu_in_reset(adev) || (adev->in_suspend && !adev->in_s0ix)) &&
+ ((amdgpu_in_reset(adev) &&
(amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) ||
((adev->in_runpm || adev->in_s4) && amdgpu_asic_supports_baco(adev)));
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index 94fcdb7bd21d..eeaa8d0d0407 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -1605,17 +1605,17 @@ void i915_vma_close(struct i915_vma *vma)
static void __i915_vma_remove_closed(struct i915_vma *vma)
{
- struct intel_gt *gt = vma->vm->gt;
-
- spin_lock_irq(&gt->closed_lock);
list_del_init(&vma->closed_link);
- spin_unlock_irq(&gt->closed_lock);
}
void i915_vma_reopen(struct i915_vma *vma)
{
+ struct intel_gt *gt = vma->vm->gt;
+
+ spin_lock_irq(&gt->closed_lock);
if (i915_vma_is_closed(vma))
__i915_vma_remove_closed(vma);
+ spin_unlock_irq(&gt->closed_lock);
}
void i915_vma_release(struct kref *ref)
@@ -1641,6 +1641,7 @@ static void force_unbind(struct i915_vma *vma)
static void release_references(struct i915_vma *vma)
{
struct drm_i915_gem_object *obj = vma->obj;
+ struct intel_gt *gt = vma->vm->gt;
GEM_BUG_ON(i915_vma_is_active(vma));
@@ -1650,7 +1651,9 @@ static void release_references(struct i915_vma *vma)
rb_erase(&vma->obj_node, &obj->vma.tree);
spin_unlock(&obj->vma.lock);
+ spin_lock_irq(&gt->closed_lock);
__i915_vma_remove_closed(vma);
+ spin_unlock_irq(&gt->closed_lock);
__i915_vma_put(vma);
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index daf9f87477ba..a2141d3d9b1d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -46,8 +46,9 @@ static bool
nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
struct nouveau_backlight *bl)
{
- const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
- if (nb < 0 || nb >= 100)
+ const int nb = ida_alloc_max(&bl_ida, 99, GFP_KERNEL);
+
+ if (nb < 0)
return false;
if (nb > 0)
snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
@@ -414,7 +415,7 @@ nouveau_backlight_init(struct drm_connector *connector)
nv_encoder, ops, &props);
if (IS_ERR(bl->dev)) {
if (bl->id >= 0)
- ida_simple_remove(&bl_ida, bl->id);
+ ida_free(&bl_ida, bl->id);
ret = PTR_ERR(bl->dev);
goto fail_alloc;
}
@@ -442,7 +443,7 @@ nouveau_backlight_fini(struct drm_connector *connector)
return;
if (bl->id >= 0)
- ida_simple_remove(&bl_ida, bl->id);
+ ida_free(&bl_ida, bl->id);
backlight_device_unregister(bl->dev);
nv_conn->backlight = NULL;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
index 992cc285f2fe..2ed528c065fa 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
@@ -123,7 +123,7 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
mutex_init(&tdev->iommu.mutex);
- if (iommu_present(&platform_bus_type)) {
+ if (device_iommu_mapped(dev)) {
tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
if (!tdev->iommu.domain)
goto error;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 6c58b0fd13fb..98b78ec6b37d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -38,6 +38,7 @@
#include <drm/drm_scdc_helper.h>
#include <linux/clk.h>
#include <linux/component.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
index a3bfbb6c3e14..162dfeb1cc5a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c
@@ -528,7 +528,7 @@ int vmw_cmd_send_fence(struct vmw_private *dev_priv, uint32_t *seqno)
*seqno = atomic_add_return(1, &dev_priv->marker_seq);
} while (*seqno == 0);
- if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE)) {
+ if (!vmw_has_fences(dev_priv)) {
/*
* Don't request hardware to send a fence. The
@@ -675,11 +675,14 @@ int vmw_cmd_emit_dummy_query(struct vmw_private *dev_priv,
*/
bool vmw_cmd_supported(struct vmw_private *vmw)
{
- if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
- SVGA_CAP_CMD_BUFFERS_2)) != 0)
- return true;
+ bool has_cmdbufs =
+ (vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
+ SVGA_CAP_CMD_BUFFERS_2)) != 0;
+ if (vmw_is_svga_v3(vmw))
+ return (has_cmdbufs &&
+ (vmw->capabilities & SVGA_CAP_GBOBJECTS) != 0);
/*
* We have FIFO cmd's
*/
- return vmw->fifo_mem != NULL;
+ return has_cmdbufs || vmw->fifo_mem != NULL;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index ea3ecdda561d..6de0b9ef5c77 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -1679,4 +1679,12 @@ static inline void vmw_irq_status_write(struct vmw_private *vmw,
outl(status, vmw->io_start + SVGA_IRQSTATUS_PORT);
}
+static inline bool vmw_has_fences(struct vmw_private *vmw)
+{
+ if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS |
+ SVGA_CAP_CMD_BUFFERS_2)) != 0)
+ return true;
+ return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0;
+}
+
#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 8ee34576c7d0..adf17c740656 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -483,7 +483,7 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par,
static int vmw_fb_kms_framebuffer(struct fb_info *info)
{
- struct drm_mode_fb_cmd2 mode_cmd;
+ struct drm_mode_fb_cmd2 mode_cmd = {0};
struct vmw_fb_par *par = info->par;
struct fb_var_screeninfo *var = &info->var;
struct drm_framebuffer *cur_fb;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index 59d6a2dd4c2e..66cc35dc223e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -82,6 +82,22 @@ fman_from_fence(struct vmw_fence_obj *fence)
return container_of(fence->base.lock, struct vmw_fence_manager, lock);
}
+static u32 vmw_fence_goal_read(struct vmw_private *vmw)
+{
+ if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
+ return vmw_read(vmw, SVGA_REG_FENCE_GOAL);
+ else
+ return vmw_fifo_mem_read(vmw, SVGA_FIFO_FENCE_GOAL);
+}
+
+static void vmw_fence_goal_write(struct vmw_private *vmw, u32 value)
+{
+ if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
+ vmw_write(vmw, SVGA_REG_FENCE_GOAL, value);
+ else
+ vmw_fifo_mem_write(vmw, SVGA_FIFO_FENCE_GOAL, value);
+}
+
/*
* Note on fencing subsystem usage of irqs:
* Typically the vmw_fences_update function is called
@@ -392,7 +408,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
if (likely(!fman->seqno_valid))
return false;
- goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL);
+ goal_seqno = vmw_fence_goal_read(fman->dev_priv);
if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP))
return false;
@@ -400,9 +416,8 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman,
list_for_each_entry(fence, &fman->fence_list, head) {
if (!list_empty(&fence->seq_passed_actions)) {
fman->seqno_valid = true;
- vmw_fifo_mem_write(fman->dev_priv,
- SVGA_FIFO_FENCE_GOAL,
- fence->base.seqno);
+ vmw_fence_goal_write(fman->dev_priv,
+ fence->base.seqno);
break;
}
}
@@ -434,13 +449,12 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence)
if (dma_fence_is_signaled_locked(&fence->base))
return false;
- goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL);
+ goal_seqno = vmw_fence_goal_read(fman->dev_priv);
if (likely(fman->seqno_valid &&
goal_seqno - fence->base.seqno < VMW_FENCE_WRAP))
return false;
- vmw_fifo_mem_write(fman->dev_priv, SVGA_FIFO_FENCE_GOAL,
- fence->base.seqno);
+ vmw_fence_goal_write(fman->dev_priv, fence->base.seqno);
fman->seqno_valid = true;
return true;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
index c5191de365ca..fe4732bf2c9d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
@@ -32,6 +32,14 @@
#define VMW_FENCE_WRAP (1 << 24)
+static u32 vmw_irqflag_fence_goal(struct vmw_private *vmw)
+{
+ if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0)
+ return SVGA_IRQFLAG_REG_FENCE_GOAL;
+ else
+ return SVGA_IRQFLAG_FENCE_GOAL;
+}
+
/**
* vmw_thread_fn - Deferred (process context) irq handler
*
@@ -96,7 +104,7 @@ static irqreturn_t vmw_irq_handler(int irq, void *arg)
wake_up_all(&dev_priv->fifo_queue);
if ((masked_status & (SVGA_IRQFLAG_ANY_FENCE |
- SVGA_IRQFLAG_FENCE_GOAL)) &&
+ vmw_irqflag_fence_goal(dev_priv))) &&
!test_and_set_bit(VMW_IRQTHREAD_FENCE, dev_priv->irqthread_pending))
ret = IRQ_WAKE_THREAD;
@@ -137,8 +145,7 @@ bool vmw_seqno_passed(struct vmw_private *dev_priv,
if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
return true;
- if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE) &&
- vmw_fifo_idle(dev_priv, seqno))
+ if (!vmw_has_fences(dev_priv) && vmw_fifo_idle(dev_priv, seqno))
return true;
/**
@@ -160,6 +167,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
unsigned long timeout)
{
struct vmw_fifo_state *fifo_state = dev_priv->fifo;
+ bool fifo_down = false;
uint32_t count = 0;
uint32_t signal_seq;
@@ -176,12 +184,14 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
*/
if (fifo_idle) {
- down_read(&fifo_state->rwsem);
if (dev_priv->cman) {
ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible,
10*HZ);
if (ret)
goto out_err;
+ } else if (fifo_state) {
+ down_read(&fifo_state->rwsem);
+ fifo_down = true;
}
}
@@ -218,12 +228,12 @@ int vmw_fallback_wait(struct vmw_private *dev_priv,
}
}
finish_wait(&dev_priv->fence_queue, &__wait);
- if (ret == 0 && fifo_idle)
+ if (ret == 0 && fifo_idle && fifo_state)
vmw_fence_write(dev_priv, signal_seq);
wake_up_all(&dev_priv->fence_queue);
out_err:
- if (fifo_idle)
+ if (fifo_down)
up_read(&fifo_state->rwsem);
return ret;
@@ -266,13 +276,13 @@ void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
void vmw_goal_waiter_add(struct vmw_private *dev_priv)
{
- vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
+ vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv),
&dev_priv->goal_queue_waiters);
}
void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
{
- vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
+ vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv),
&dev_priv->goal_queue_waiters);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index bbd2f4ec08ec..93431e8f6606 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1344,7 +1344,6 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb,
mode_cmd,
is_bo_proxy);
-
/*
* vmw_create_bo_proxy() adds a reference that is no longer
* needed
@@ -1385,13 +1384,16 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
ret = vmw_user_lookup_handle(dev_priv, file_priv,
mode_cmd->handles[0],
&surface, &bo);
- if (ret)
+ if (ret) {
+ DRM_ERROR("Invalid buffer object handle %u (0x%x).\n",
+ mode_cmd->handles[0], mode_cmd->handles[0]);
goto err_out;
+ }
if (!bo &&
!vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)) {
- DRM_ERROR("Surface size cannot exceed %dx%d",
+ DRM_ERROR("Surface size cannot exceed %dx%d\n",
dev_priv->texture_max_width,
dev_priv->texture_max_height);
goto err_out;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 68a8a27ab3b7..f2b038fa3b84 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -960,7 +960,7 @@ config SENSORS_LTC4261
config SENSORS_LTQ_CPUTEMP
bool "Lantiq cpu temperature sensor driver"
- depends on LANTIQ
+ depends on SOC_XWAY
help
If you say yes here you get support for the temperature
sensor inside your CPU.
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index b86d9df7105d..52c9e7d3f2ae 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -708,10 +708,21 @@ static int tmp401_probe(struct i2c_client *client)
return 0;
}
+static const struct of_device_id __maybe_unused tmp4xx_of_match[] = {
+ { .compatible = "ti,tmp401", },
+ { .compatible = "ti,tmp411", },
+ { .compatible = "ti,tmp431", },
+ { .compatible = "ti,tmp432", },
+ { .compatible = "ti,tmp435", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tmp4xx_of_match);
+
static struct i2c_driver tmp401_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "tmp401",
+ .of_match_table = of_match_ptr(tmp4xx_of_match),
},
.probe_new = tmp401_probe,
.id_table = tmp401_id,
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 9050ca1f4285..808f6e7a8048 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -1087,9 +1087,15 @@ static int of_count_icc_providers(struct device_node *np)
{
struct device_node *child;
int count = 0;
+ const struct of_device_id __maybe_unused ignore_list[] = {
+ { .compatible = "qcom,sc7180-ipa-virt" },
+ { .compatible = "qcom,sdx55-ipa-virt" },
+ {}
+ };
for_each_available_child_of_node(np, child) {
- if (of_property_read_bool(child, "#interconnect-cells"))
+ if (of_property_read_bool(child, "#interconnect-cells") &&
+ likely(!of_match_node(ignore_list, child)))
count++;
count += of_count_icc_providers(child);
}
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index ac760fd39282..b2dcc1e5a388 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -71,23 +71,6 @@ config CAN_CALC_BITTIMING
arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
If unsure, say Y.
-config CAN_LEDS
- bool "Enable LED triggers for Netlink based drivers"
- depends on LEDS_CLASS
- # The netdev trigger (LEDS_TRIGGER_NETDEV) should be able to do
- # everything that this driver is doing. This is marked as broken
- # because it uses stuff that is intended to be changed or removed.
- # Please consider switching to the netdev trigger and confirm it
- # fulfills your needs instead of fixing this driver.
- depends on BROKEN
- select LEDS_TRIGGERS
- help
- This option adds two LED triggers for packet receive and transmit
- events on each supported CAN device.
-
- Say Y here if you are working on a system with led-class supported
- LEDs and you want to use them as canbus activity indicators.
-
config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
depends on (ARCH_AT91 || COMPILE_TEST) && HAS_IOMEM
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index a00655ccda02..29ed0d3cd171 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -23,7 +23,6 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#define AT91_MB_MASK(i) ((1 << (i)) - 1)
@@ -618,8 +617,6 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
stats->rx_bytes += cf->len;
netif_receive_skb(skb);
-
- can_led_event(dev, CAN_LED_EVENT_RX);
}
/**
@@ -854,7 +851,6 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
mb - get_mb_tx_first(priv),
NULL);
dev->stats.tx_packets++;
- can_led_event(dev, CAN_LED_EVENT_TX);
}
}
@@ -1101,8 +1097,6 @@ static int at91_open(struct net_device *dev)
goto out_close;
}
- can_led_event(dev, CAN_LED_EVENT_OPEN);
-
/* start chip and queuing */
at91_chip_start(dev);
napi_enable(&priv->napi);
@@ -1133,8 +1127,6 @@ static int at91_close(struct net_device *dev)
close_candev(dev);
- can_led_event(dev, CAN_LED_EVENT_STOP);
-
return 0;
}
@@ -1317,7 +1309,7 @@ static int at91_can_probe(struct platform_device *pdev)
priv->pdata = dev_get_platdata(&pdev->dev);
priv->mb0_id = 0x7ff;
- netif_napi_add(dev, &priv->napi, at91_poll, get_mb_rx_num(priv));
+ netif_napi_add_weight(dev, &priv->napi, at91_poll, get_mb_rx_num(priv));
if (at91_is_sam9263(priv))
dev->sysfs_groups[0] = &at91_sysfs_attr_group;
@@ -1331,8 +1323,6 @@ static int at91_can_probe(struct platform_device *pdev)
goto exit_free;
}
- devm_can_led_init(dev);
-
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
priv->reg_base, dev->irq);
diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c
index faa217f26771..a7362af0babb 100644
--- a/drivers/net/can/c_can/c_can_main.c
+++ b/drivers/net/can/c_can/c_can_main.c
@@ -40,7 +40,6 @@
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include "c_can.h"
@@ -759,7 +758,6 @@ static void c_can_do_tx(struct net_device *dev)
stats->tx_bytes += bytes;
stats->tx_packets += pkts;
- can_led_event(dev, CAN_LED_EVENT_TX);
tail = c_can_get_tx_tail(tx_ring);
@@ -906,9 +904,6 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
quota -= n;
}
- if (pkts)
- can_led_event(dev, CAN_LED_EVENT_RX);
-
return pkts;
}
@@ -1182,8 +1177,6 @@ static int c_can_open(struct net_device *dev)
if (err)
goto exit_start_fail;
- can_led_event(dev, CAN_LED_EVENT_OPEN);
-
napi_enable(&priv->napi);
/* enable status change, error and module interrupts */
c_can_irq_control(priv, true);
@@ -1214,8 +1207,6 @@ static int c_can_close(struct net_device *dev)
c_can_reset_ram(priv, false);
c_can_pm_runtime_put_sync(priv);
- can_led_event(dev, CAN_LED_EVENT_STOP);
-
return 0;
}
@@ -1246,7 +1237,8 @@ struct net_device *alloc_c_can_dev(int msg_obj_num)
priv->tx.tail = 0;
priv->tx.obj_num = msg_obj_tx_num;
- netif_napi_add(dev, &priv->napi, c_can_poll, priv->msg_obj_rx_num);
+ netif_napi_add_weight(dev, &priv->napi, c_can_poll,
+ priv->msg_obj_rx_num);
priv->dev = dev;
priv->can.bittiming_const = &c_can_bittiming_const;
@@ -1364,8 +1356,6 @@ static const struct net_device_ops c_can_netdev_ops = {
int register_c_can_dev(struct net_device *dev)
{
- int err;
-
/* Deactivate pins to prevent DRA7 DCAN IP from being
* stuck in transition when module is disabled.
* Pins are activated in c_can_start() and deactivated
@@ -1377,10 +1367,7 @@ int register_c_can_dev(struct net_device *dev)
dev->netdev_ops = &c_can_netdev_ops;
c_can_set_ethtool_ops(dev);
- err = register_candev(dev);
- if (!err)
- devm_can_led_init(dev);
- return err;
+ return register_candev(dev);
}
EXPORT_SYMBOL_GPL(register_c_can_dev);
diff --git a/drivers/net/can/ctucanfd/Kconfig b/drivers/net/can/ctucanfd/Kconfig
index 48963efc7f19..3c383612eb17 100644
--- a/drivers/net/can/ctucanfd/Kconfig
+++ b/drivers/net/can/ctucanfd/Kconfig
@@ -1,5 +1,5 @@
config CAN_CTUCANFD
- tristate "CTU CAN-FD IP core"
+ tristate "CTU CAN-FD IP core" if COMPILE_TEST
help
This driver adds support for the CTU CAN FD open-source IP core.
More documentation and core sources at project page
@@ -13,8 +13,8 @@ config CAN_CTUCANFD
config CAN_CTUCANFD_PCI
tristate "CTU CAN-FD IP core PCI/PCIe driver"
- depends on CAN_CTUCANFD
depends on PCI
+ select CAN_CTUCANFD
help
This driver adds PCI/PCIe support for CTU CAN-FD IP core.
The project providing FPGA design for Intel EP4CGX15 based DB4CGX15
@@ -23,8 +23,8 @@ config CAN_CTUCANFD_PCI
config CAN_CTUCANFD_PLATFORM
tristate "CTU CAN-FD IP core platform (FPGA, SoC) driver"
- depends on CAN_CTUCANFD
depends on OF || COMPILE_TEST
+ select CAN_CTUCANFD
help
The core has been tested together with OpenCores SJA1000
modified to be CAN FD frames tolerant on MicroZed Zynq based
diff --git a/drivers/net/can/ctucanfd/ctucanfd_base.c b/drivers/net/can/ctucanfd/ctucanfd_base.c
index 2ada097d1ede..64990bf20fdc 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_base.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_base.c
@@ -29,7 +29,6 @@
#include <linux/string.h>
#include <linux/types.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include <linux/pm_runtime.h>
#include "ctucanfd.h"
@@ -957,9 +956,6 @@ static int ctucan_rx_poll(struct napi_struct *napi, int quota)
ctucan_write32(priv, CTUCANFD_COMMAND, REG_COMMAND_CDO);
}
- if (work_done)
- can_led_event(ndev, CAN_LED_EVENT_RX);
-
if (!framecnt && res != 0) {
if (napi_complete_done(napi, work_done)) {
/* Clear and enable RBNEI. It is level-triggered, so
@@ -1079,8 +1075,6 @@ clear:
}
} while (some_buffers_processed);
- can_led_event(ndev, CAN_LED_EVENT_TX);
-
spin_lock_irqsave(&priv->tx_lock, flags);
/* Check if at least one TX buffer is free */
@@ -1236,7 +1230,6 @@ static int ctucan_open(struct net_device *ndev)
}
netdev_info(ndev, "ctu_can_fd device registered\n");
- can_led_event(ndev, CAN_LED_EVENT_OPEN);
napi_enable(&priv->napi);
netif_start_queue(ndev);
@@ -1269,7 +1262,6 @@ static int ctucan_close(struct net_device *ndev)
free_irq(ndev->irq, ndev);
close_candev(ndev);
- can_led_event(ndev, CAN_LED_EVENT_STOP);
pm_runtime_put(priv->dev);
return 0;
@@ -1434,8 +1426,6 @@ int ctucan_probe_common(struct device *dev, void __iomem *addr, int irq, unsigne
goto err_deviceoff;
}
- devm_can_led_init(ndev);
-
pm_runtime_put(dev);
netdev_dbg(ndev, "mem_base=0x%p irq=%d clock=%d, no. of txt buffers:%d\n",
diff --git a/drivers/net/can/dev/Makefile b/drivers/net/can/dev/Makefile
index 3e2e207861fc..af2901db473c 100644
--- a/drivers/net/can/dev/Makefile
+++ b/drivers/net/can/dev/Makefile
@@ -7,5 +7,3 @@ can-dev-y += length.o
can-dev-y += netlink.o
can-dev-y += rx-offload.o
can-dev-y += skb.o
-
-can-dev-$(CONFIG_CAN_LEDS) += led.o
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index e7ab45f1c43b..96c9d9db00cf 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -14,7 +14,6 @@
#include <linux/can/can-ml.h>
#include <linux/can/dev.h>
#include <linux/can/skb.h>
-#include <linux/can/led.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
@@ -512,8 +511,6 @@ static __init int can_dev_init(void)
{
int err;
- can_led_notifier_init();
-
err = can_netlink_register();
if (!err)
pr_info(MOD_DESC "\n");
@@ -525,8 +522,6 @@ module_init(can_dev_init);
static __exit void can_dev_exit(void)
{
can_netlink_unregister();
-
- can_led_notifier_exit();
}
module_exit(can_dev_exit);
diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
index 6d0dc18c03e7..a32a01c172d4 100644
--- a/drivers/net/can/dev/rx-offload.c
+++ b/drivers/net/can/dev/rx-offload.c
@@ -70,8 +70,6 @@ static int can_rx_offload_napi_poll(struct napi_struct *napi, int quota)
napi_reschedule(&offload->napi);
}
- can_led_event(offload->dev, CAN_LED_EVENT_RX);
-
return work_done;
}
@@ -337,7 +335,8 @@ static int can_rx_offload_init_queue(struct net_device *dev,
skb_queue_head_init(&offload->skb_queue);
__skb_queue_head_init(&offload->skb_irq_queue);
- netif_napi_add(dev, &offload->napi, can_rx_offload_napi_poll, weight);
+ netif_napi_add_weight(dev, &offload->napi, can_rx_offload_napi_poll,
+ weight);
dev_dbg(dev->dev.parent, "%s: skb_queue_len_max=%d\n",
__func__, offload->skb_queue_len_max);
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index fe9bda0f5ec4..d060088047f1 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -14,7 +14,6 @@
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/firmware/imx/sci.h>
@@ -1081,7 +1080,6 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
can_rx_offload_get_echo_skb(&priv->offload, 0,
reg_ctrl << 16, NULL);
stats->tx_packets++;
- can_led_event(dev, CAN_LED_EVENT_TX);
/* after sending a RTR frame MB is in RX mode */
priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
@@ -1738,8 +1736,6 @@ static int flexcan_open(struct net_device *dev)
flexcan_chip_interrupts_enable(dev);
- can_led_event(dev, CAN_LED_EVENT_OPEN);
-
netif_start_queue(dev);
return 0;
@@ -1785,8 +1781,6 @@ static int flexcan_close(struct net_device *dev)
pm_runtime_put(priv->dev);
- can_led_event(dev, CAN_LED_EVENT_STOP);
-
return 0;
}
@@ -2189,7 +2183,6 @@ static int flexcan_probe(struct platform_device *pdev)
}
of_can_transceiver(dev);
- devm_can_led_init(dev);
return 0;
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index 5215bd9b2c80..76df4807d366 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -1609,7 +1609,7 @@ static int grcan_setup_netdev(struct platform_device *ofdev,
timer_setup(&priv->hang_timer, grcan_initiate_running_reset, 0);
}
- netif_napi_add(dev, &priv->napi, grcan_poll, GRCAN_NAPI_WEIGHT);
+ netif_napi_add_weight(dev, &priv->napi, grcan_poll, GRCAN_NAPI_WEIGHT);
SET_NETDEV_DEV(dev, &ofdev->dev);
dev_info(&ofdev->dev, "regs=0x%p, irq=%d, clock=%d\n",
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index b0a3473f211d..968ed6d7316b 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -345,9 +345,6 @@ static int ifi_canfd_do_rx_poll(struct net_device *ndev, int quota)
rxst = readl(priv->base + IFI_CANFD_RXSTCMD);
}
- if (pkts)
- can_led_event(ndev, CAN_LED_EVENT_RX);
-
return pkts;
}
@@ -626,7 +623,6 @@ static irqreturn_t ifi_canfd_isr(int irq, void *dev_id)
if (isr & IFI_CANFD_INTERRUPT_TXFIFO_REMOVE) {
stats->tx_bytes += can_get_echo_skb(ndev, 0, NULL);
stats->tx_packets++;
- can_led_event(ndev, CAN_LED_EVENT_TX);
}
if (isr & tx_irq_mask)
@@ -830,7 +826,6 @@ static int ifi_canfd_open(struct net_device *ndev)
ifi_canfd_start(ndev);
- can_led_event(ndev, CAN_LED_EVENT_OPEN);
napi_enable(&priv->napi);
netif_start_queue(ndev);
@@ -853,8 +848,6 @@ static int ifi_canfd_close(struct net_device *ndev)
close_candev(ndev);
- can_led_event(ndev, CAN_LED_EVENT_STOP);
-
return 0;
}
@@ -1004,8 +997,6 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev)
goto err_reg;
}
- devm_can_led_init(ndev);
-
dev_info(dev, "Driver registered: regs=%p, irq=%d, clock=%d\n",
priv->base, ndev->irq, priv->can.clock.freq);
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index 808c105cf8f7..35bfb82d6929 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -1910,7 +1910,7 @@ static int ican3_probe(struct platform_device *pdev)
mod = netdev_priv(ndev);
mod->ndev = ndev;
mod->num = pdata->modno;
- netif_napi_add(ndev, &mod->napi, ican3_napi, ICAN3_RX_BUFFERS);
+ netif_napi_add_weight(ndev, &mod->napi, ican3_napi, ICAN3_RX_BUFFERS);
skb_queue_head_init(&mod->echoq);
spin_lock_init(&mod->lock);
init_completion(&mod->termination_comp);
diff --git a/drivers/net/can/led.c b/drivers/net/can/led.c
deleted file mode 100644
index db14897f8e16..000000000000
--- a/drivers/net/can/led.c
+++ /dev/null
@@ -1,140 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
- * Copyright 2012, Kurt Van Dijck <kurt.van.dijck@eia.be>
- */
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/can/dev.h>
-
-#include <linux/can/led.h>
-
-static unsigned long led_delay = 50;
-module_param(led_delay, ulong, 0644);
-MODULE_PARM_DESC(led_delay,
- "blink delay time for activity leds (msecs, default: 50).");
-
-/* Trigger a LED event in response to a CAN device event */
-void can_led_event(struct net_device *netdev, enum can_led_event event)
-{
- struct can_priv *priv = netdev_priv(netdev);
-
- switch (event) {
- case CAN_LED_EVENT_OPEN:
- led_trigger_event(priv->tx_led_trig, LED_FULL);
- led_trigger_event(priv->rx_led_trig, LED_FULL);
- led_trigger_event(priv->rxtx_led_trig, LED_FULL);
- break;
- case CAN_LED_EVENT_STOP:
- led_trigger_event(priv->tx_led_trig, LED_OFF);
- led_trigger_event(priv->rx_led_trig, LED_OFF);
- led_trigger_event(priv->rxtx_led_trig, LED_OFF);
- break;
- case CAN_LED_EVENT_TX:
- if (led_delay) {
- led_trigger_blink_oneshot(priv->tx_led_trig,
- &led_delay, &led_delay, 1);
- led_trigger_blink_oneshot(priv->rxtx_led_trig,
- &led_delay, &led_delay, 1);
- }
- break;
- case CAN_LED_EVENT_RX:
- if (led_delay) {
- led_trigger_blink_oneshot(priv->rx_led_trig,
- &led_delay, &led_delay, 1);
- led_trigger_blink_oneshot(priv->rxtx_led_trig,
- &led_delay, &led_delay, 1);
- }
- break;
- }
-}
-EXPORT_SYMBOL_GPL(can_led_event);
-
-static void can_led_release(struct device *gendev, void *res)
-{
- struct can_priv *priv = netdev_priv(to_net_dev(gendev));
-
- led_trigger_unregister_simple(priv->tx_led_trig);
- led_trigger_unregister_simple(priv->rx_led_trig);
- led_trigger_unregister_simple(priv->rxtx_led_trig);
-}
-
-/* Register CAN LED triggers for a CAN device
- *
- * This is normally called from a driver's probe function
- */
-void devm_can_led_init(struct net_device *netdev)
-{
- struct can_priv *priv = netdev_priv(netdev);
- void *res;
-
- res = devres_alloc(can_led_release, 0, GFP_KERNEL);
- if (!res) {
- netdev_err(netdev, "cannot register LED triggers\n");
- return;
- }
-
- snprintf(priv->tx_led_trig_name, sizeof(priv->tx_led_trig_name),
- "%s-tx", netdev->name);
- snprintf(priv->rx_led_trig_name, sizeof(priv->rx_led_trig_name),
- "%s-rx", netdev->name);
- snprintf(priv->rxtx_led_trig_name, sizeof(priv->rxtx_led_trig_name),
- "%s-rxtx", netdev->name);
-
- led_trigger_register_simple(priv->tx_led_trig_name,
- &priv->tx_led_trig);
- led_trigger_register_simple(priv->rx_led_trig_name,
- &priv->rx_led_trig);
- led_trigger_register_simple(priv->rxtx_led_trig_name,
- &priv->rxtx_led_trig);
-
- devres_add(&netdev->dev, res);
-}
-EXPORT_SYMBOL_GPL(devm_can_led_init);
-
-/* NETDEV rename notifier to rename the associated led triggers too */
-static int can_led_notifier(struct notifier_block *nb, unsigned long msg,
- void *ptr)
-{
- struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
- struct can_priv *priv = safe_candev_priv(netdev);
- char name[CAN_LED_NAME_SZ];
-
- if (!priv)
- return NOTIFY_DONE;
-
- if (!priv->tx_led_trig || !priv->rx_led_trig || !priv->rxtx_led_trig)
- return NOTIFY_DONE;
-
- if (msg == NETDEV_CHANGENAME) {
- snprintf(name, sizeof(name), "%s-tx", netdev->name);
- led_trigger_rename_static(name, priv->tx_led_trig);
-
- snprintf(name, sizeof(name), "%s-rx", netdev->name);
- led_trigger_rename_static(name, priv->rx_led_trig);
-
- snprintf(name, sizeof(name), "%s-rxtx", netdev->name);
- led_trigger_rename_static(name, priv->rxtx_led_trig);
- }
-
- return NOTIFY_DONE;
-}
-
-/* notifier block for netdevice event */
-static struct notifier_block can_netdev_notifier __read_mostly = {
- .notifier_call = can_led_notifier,
-};
-
-int __init can_led_notifier_init(void)
-{
- return register_netdevice_notifier(&can_netdev_notifier);
-}
-
-void __exit can_led_notifier_exit(void)
-{
- unregister_netdevice_notifier(&can_netdev_notifier);
-}
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index e6d2da4a9f41..5d0c82d8b9a9 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -565,9 +565,6 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota)
rxfs = m_can_read(cdev, M_CAN_RXF0S);
}
- if (pkts)
- can_led_event(dev, CAN_LED_EVENT_RX);
-
return pkts;
}
@@ -1087,8 +1084,6 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
if (cdev->is_peripheral)
timestamp = m_can_get_timestamp(cdev);
m_can_tx_update_stats(cdev, 0, timestamp);
-
- can_led_event(dev, CAN_LED_EVENT_TX);
netif_wake_queue(dev);
}
} else {
@@ -1097,7 +1092,6 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
if (m_can_echo_tx_event(dev) != 0)
goto out_fail;
- can_led_event(dev, CAN_LED_EVENT_TX);
if (netif_queue_stopped(dev) &&
!m_can_tx_fifo_full(cdev))
netif_wake_queue(dev);
@@ -1492,34 +1486,22 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
err = can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
if (err)
return err;
- cdev->can.bittiming_const = cdev->bit_timing ?
- cdev->bit_timing : &m_can_bittiming_const_30X;
-
- cdev->can.data_bittiming_const = cdev->data_timing ?
- cdev->data_timing :
- &m_can_data_bittiming_const_30X;
+ cdev->can.bittiming_const = &m_can_bittiming_const_30X;
+ cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X;
break;
case 31:
/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */
err = can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
if (err)
return err;
- cdev->can.bittiming_const = cdev->bit_timing ?
- cdev->bit_timing : &m_can_bittiming_const_31X;
-
- cdev->can.data_bittiming_const = cdev->data_timing ?
- cdev->data_timing :
- &m_can_data_bittiming_const_31X;
+ cdev->can.bittiming_const = &m_can_bittiming_const_31X;
+ cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
break;
case 32:
case 33:
/* Support both MCAN version v3.2.x and v3.3.0 */
- cdev->can.bittiming_const = cdev->bit_timing ?
- cdev->bit_timing : &m_can_bittiming_const_31X;
-
- cdev->can.data_bittiming_const = cdev->data_timing ?
- cdev->data_timing :
- &m_can_data_bittiming_const_31X;
+ cdev->can.bittiming_const = &m_can_bittiming_const_31X;
+ cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
cdev->can.ctrlmode_supported |=
(m_can_niso_supported(cdev) ?
@@ -1574,7 +1556,6 @@ static int m_can_close(struct net_device *dev)
can_rx_offload_disable(&cdev->offload);
close_candev(dev);
- can_led_event(dev, CAN_LED_EVENT_STOP);
phy_power_off(cdev->transceiver);
@@ -1818,8 +1799,6 @@ static int m_can_open(struct net_device *dev)
/* start the m_can controller */
m_can_start(dev);
- can_led_event(dev, CAN_LED_EVENT_OPEN);
-
if (!cdev->is_peripheral)
napi_enable(&cdev->napi);
@@ -2007,8 +1986,6 @@ int m_can_class_register(struct m_can_classdev *cdev)
goto rx_offload_del;
}
- devm_can_led_init(cdev->net);
-
of_can_transceiver(cdev->net);
dev_info(cdev->dev, "%s device registered (irq=%d, version=%d)\n",
diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h
index 2c5d40997168..4c0267f9f297 100644
--- a/drivers/net/can/m_can/m_can.h
+++ b/drivers/net/can/m_can/m_can.h
@@ -7,7 +7,6 @@
#define _CAN_M_CAN_H_
#include <linux/can/core.h>
-#include <linux/can/led.h>
#include <linux/can/rx-offload.h>
#include <linux/completion.h>
#include <linux/device.h>
@@ -85,9 +84,6 @@ struct m_can_classdev {
struct sk_buff *tx_skb;
struct phy *transceiver;
- const struct can_bittiming_const *bit_timing;
- const struct can_bittiming_const *data_timing;
-
struct m_can_ops *ops;
int version;
diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
index b56a54d6c5a9..8f184a852a0a 100644
--- a/drivers/net/can/m_can/m_can_pci.c
+++ b/drivers/net/can/m_can/m_can_pci.c
@@ -18,14 +18,9 @@
#define M_CAN_PCI_MMIO_BAR 0
+#define M_CAN_CLOCK_FREQ_EHL 200000000
#define CTL_CSR_INT_CTL_OFFSET 0x508
-struct m_can_pci_config {
- const struct can_bittiming_const *bit_timing;
- const struct can_bittiming_const *data_timing;
- unsigned int clock_freq;
-};
-
struct m_can_pci_priv {
struct m_can_classdev cdev;
@@ -89,40 +84,9 @@ static struct m_can_ops m_can_pci_ops = {
.read_fifo = iomap_read_fifo,
};
-static const struct can_bittiming_const m_can_bittiming_const_ehl = {
- .name = KBUILD_MODNAME,
- .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */
- .tseg1_max = 64,
- .tseg2_min = 1, /* Time segment 2 = phase_seg2 */
- .tseg2_max = 128,
- .sjw_max = 128,
- .brp_min = 1,
- .brp_max = 512,
- .brp_inc = 1,
-};
-
-static const struct can_bittiming_const m_can_data_bittiming_const_ehl = {
- .name = KBUILD_MODNAME,
- .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */
- .tseg1_max = 16,
- .tseg2_min = 1, /* Time segment 2 = phase_seg2 */
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 32,
- .brp_inc = 1,
-};
-
-static const struct m_can_pci_config m_can_pci_ehl = {
- .bit_timing = &m_can_bittiming_const_ehl,
- .data_timing = &m_can_data_bittiming_const_ehl,
- .clock_freq = 200000000,
-};
-
static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
{
struct device *dev = &pci->dev;
- const struct m_can_pci_config *cfg;
struct m_can_classdev *mcan_class;
struct m_can_pci_priv *priv;
void __iomem *base;
@@ -150,8 +114,6 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
if (!mcan_class)
return -ENOMEM;
- cfg = (const struct m_can_pci_config *)id->driver_data;
-
priv = cdev_to_priv(mcan_class);
priv->base = base;
@@ -163,9 +125,7 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
mcan_class->dev = &pci->dev;
mcan_class->net->irq = pci_irq_vector(pci, 0);
mcan_class->pm_clock_support = 1;
- mcan_class->bit_timing = cfg->bit_timing;
- mcan_class->data_timing = cfg->data_timing;
- mcan_class->can.clock.freq = cfg->clock_freq;
+ mcan_class->can.clock.freq = id->driver_data;
mcan_class->ops = &m_can_pci_ops;
pci_set_drvdata(pci, mcan_class);
@@ -218,8 +178,8 @@ static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
m_can_pci_suspend, m_can_pci_resume);
static const struct pci_device_id m_can_pci_id_table[] = {
- { PCI_VDEVICE(INTEL, 0x4bc1), (kernel_ulong_t)&m_can_pci_ehl, },
- { PCI_VDEVICE(INTEL, 0x4bc2), (kernel_ulong_t)&m_can_pci_ehl, },
+ { PCI_VDEVICE(INTEL, 0x4bc1), M_CAN_CLOCK_FREQ_EHL, },
+ { PCI_VDEVICE(INTEL, 0x4bc2), M_CAN_CLOCK_FREQ_EHL, },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, m_can_pci_id_table);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 5b5802fac772..78a21ab63601 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -679,7 +679,7 @@ struct net_device *alloc_mscandev(void)
dev->flags |= IFF_ECHO; /* we support local echo */
- netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8);
+ netif_napi_add_weight(dev, &priv->napi, mscan_rx_poll, 8);
priv->can.bittiming_const = &mscan_bittiming_const;
priv->can.do_set_bittiming = mscan_do_set_bittiming;
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 888bef03de09..fde3ac516d26 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -1189,7 +1189,7 @@ static int pch_can_probe(struct pci_dev *pdev,
ndev->netdev_ops = &pch_can_netdev_ops;
priv->can.clock.freq = PCH_CAN_CLK; /* Hz */
- netif_napi_add(ndev, &priv->napi, pch_can_poll, PCH_RX_OBJ_END);
+ netif_napi_add_weight(ndev, &priv->napi, pch_can_poll, PCH_RX_OBJ_END);
rc = pci_enable_msi(priv->dev);
if (rc) {
diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c
index 33e37395379d..d45762f1cf6b 100644
--- a/drivers/net/can/rcar/rcar_can.c
+++ b/drivers/net/can/rcar/rcar_can.c
@@ -12,7 +12,6 @@
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/platform_device.h>
-#include <linux/can/led.h>
#include <linux/can/dev.h>
#include <linux/clk.h>
#include <linux/of.h>
@@ -389,7 +388,6 @@ static void rcar_can_tx_done(struct net_device *ndev)
/* Clear interrupt */
isr = readb(&priv->regs->isr);
writeb(isr & ~RCAR_CAN_ISR_TXFF, &priv->regs->isr);
- can_led_event(ndev, CAN_LED_EVENT_TX);
}
static irqreturn_t rcar_can_interrupt(int irq, void *dev_id)
@@ -531,7 +529,6 @@ static int rcar_can_open(struct net_device *ndev)
ndev->irq, err);
goto out_close;
}
- can_led_event(ndev, CAN_LED_EVENT_OPEN);
rcar_can_start(ndev);
netif_start_queue(ndev);
return 0;
@@ -581,7 +578,6 @@ static int rcar_can_close(struct net_device *ndev)
clk_disable_unprepare(priv->can_clk);
clk_disable_unprepare(priv->clk);
close_candev(ndev);
- can_led_event(ndev, CAN_LED_EVENT_STOP);
return 0;
}
@@ -666,8 +662,6 @@ static void rcar_can_rx_pkt(struct rcar_can_priv *priv)
}
stats->rx_packets++;
- can_led_event(priv->ndev, CAN_LED_EVENT_RX);
-
netif_receive_skb(skb);
}
@@ -803,8 +797,8 @@ static int rcar_can_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ndev);
SET_NETDEV_DEV(ndev, &pdev->dev);
- netif_napi_add(ndev, &priv->napi, rcar_can_rx_poll,
- RCAR_CAN_NAPI_WEIGHT);
+ netif_napi_add_weight(ndev, &priv->napi, rcar_can_rx_poll,
+ RCAR_CAN_NAPI_WEIGHT);
err = register_candev(ndev);
if (err) {
dev_err(&pdev->dev, "register_candev() failed, error %d\n",
@@ -812,8 +806,6 @@ static int rcar_can_probe(struct platform_device *pdev)
goto fail_candev;
}
- devm_can_led_init(ndev);
-
dev_info(&pdev->dev, "device registered (IRQ%d)\n", ndev->irq);
return 0;
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 1e121e04208c..40a11445d021 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -29,7 +29,6 @@
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/platform_device.h>
-#include <linux/can/led.h>
#include <linux/can/dev.h>
#include <linux/clk.h>
#include <linux/of.h>
@@ -1128,7 +1127,6 @@ static void rcar_canfd_tx_done(struct net_device *ndev)
/* Clear interrupt */
rcar_canfd_write(priv->base, RCANFD_CFSTS(gpriv, ch, RCANFD_CFFIFO_IDX),
sts & ~RCANFD_CFSTS_CFTXIF);
- can_led_event(ndev, CAN_LED_EVENT_TX);
}
static void rcar_canfd_handle_global_err(struct rcar_canfd_global *gpriv, u32 ch)
@@ -1419,7 +1417,6 @@ static int rcar_canfd_open(struct net_device *ndev)
if (err)
goto out_close;
netif_start_queue(ndev);
- can_led_event(ndev, CAN_LED_EVENT_OPEN);
return 0;
out_close:
napi_disable(&priv->napi);
@@ -1469,7 +1466,6 @@ static int rcar_canfd_close(struct net_device *ndev)
napi_disable(&priv->napi);
clk_disable_unprepare(gpriv->can_clk);
close_candev(ndev);
- can_led_event(ndev, CAN_LED_EVENT_STOP);
return 0;
}
@@ -1619,8 +1615,6 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
*/
rcar_canfd_write(priv->base, RCANFD_RFPCTR(gpriv, ridx), 0xff);
- can_led_event(priv->ndev, CAN_LED_EVENT_RX);
-
if (!(cf->can_id & CAN_RTR_FLAG))
stats->rx_bytes += cf->len;
stats->rx_packets++;
@@ -1789,10 +1783,9 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
priv->gpriv = gpriv;
SET_NETDEV_DEV(ndev, &pdev->dev);
- netif_napi_add(ndev, &priv->napi, rcar_canfd_rx_poll,
- RCANFD_NAPI_WEIGHT);
+ netif_napi_add_weight(ndev, &priv->napi, rcar_canfd_rx_poll,
+ RCANFD_NAPI_WEIGHT);
spin_lock_init(&priv->tx_lock);
- devm_can_led_init(ndev);
gpriv->ch[priv->channel] = priv;
err = register_candev(ndev);
if (err) {
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index 966316479485..2e7638f98cf1 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -60,7 +60,6 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include "sja1000.h"
@@ -383,8 +382,6 @@ static void sja1000_rx(struct net_device *dev)
sja1000_write_cmdreg(priv, CMD_RRB);
netif_rx(skb);
-
- can_led_event(dev, CAN_LED_EVENT_RX);
}
static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
@@ -531,7 +528,6 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
stats->tx_packets++;
}
netif_wake_queue(dev);
- can_led_event(dev, CAN_LED_EVENT_TX);
}
if (isrc & IRQ_RI) {
/* receive interrupt */
@@ -587,8 +583,6 @@ static int sja1000_open(struct net_device *dev)
/* init and start chi */
sja1000_start(dev);
- can_led_event(dev, CAN_LED_EVENT_OPEN);
-
netif_start_queue(dev);
return 0;
@@ -606,8 +600,6 @@ static int sja1000_close(struct net_device *dev)
close_candev(dev);
- can_led_event(dev, CAN_LED_EVENT_STOP);
-
return 0;
}
@@ -673,9 +665,6 @@ int register_sja1000dev(struct net_device *dev)
ret = register_candev(dev);
- if (!ret)
- devm_can_led_init(dev);
-
return ret;
}
EXPORT_SYMBOL_GPL(register_sja1000dev);
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index ec294d0c5722..64a3aee8a7da 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -359,8 +359,8 @@ static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct slcan *sl = netdev_priv(dev);
- if (skb->len != CAN_MTU)
- goto out;
+ if (can_dropped_invalid_skb(dev, skb))
+ return NETDEV_TX_OK;
spin_lock(&sl->lock);
if (!netif_running(dev)) {
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
index a5b2952b8d0f..ebc4ebb44c98 100644
--- a/drivers/net/can/spi/hi311x.c
+++ b/drivers/net/can/spi/hi311x.c
@@ -16,7 +16,6 @@
#include <linux/can/core.h>
#include <linux/can/dev.h>
-#include <linux/can/led.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
@@ -354,8 +353,6 @@ static void hi3110_hw_rx(struct spi_device *spi)
}
priv->net->stats.rx_packets++;
- can_led_event(priv->net, CAN_LED_EVENT_RX);
-
netif_rx(skb);
}
@@ -567,8 +564,6 @@ static int hi3110_stop(struct net_device *net)
mutex_unlock(&priv->hi3110_lock);
- can_led_event(net, CAN_LED_EVENT_STOP);
-
return 0;
}
@@ -725,7 +720,6 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
if (priv->tx_busy && statf & HI3110_STAT_TXMTY) {
net->stats.tx_packets++;
net->stats.tx_bytes += can_get_echo_skb(net, 0, NULL);
- can_led_event(net, CAN_LED_EVENT_TX);
priv->tx_busy = false;
netif_wake_queue(net);
}
@@ -783,7 +777,6 @@ static int hi3110_open(struct net_device *net)
if (ret)
goto out_free_wq;
- can_led_event(net, CAN_LED_EVENT_OPEN);
netif_wake_queue(net);
mutex_unlock(&priv->hi3110_lock);
@@ -931,7 +924,6 @@ static int hi3110_can_probe(struct spi_device *spi)
if (ret)
goto error_probe;
- devm_can_led_init(net);
netdev_info(net, "%x successfully initialized.\n", priv->model);
return 0;
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index fc747bff5eeb..666a4505a55a 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -22,7 +22,6 @@
#include <linux/bitfield.h>
#include <linux/can/core.h>
#include <linux/can/dev.h>
-#include <linux/can/led.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
@@ -738,8 +737,6 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
}
priv->net->stats.rx_packets++;
- can_led_event(priv->net, CAN_LED_EVENT_RX);
-
netif_rx(skb);
}
@@ -973,8 +970,6 @@ static int mcp251x_stop(struct net_device *net)
mutex_unlock(&priv->mcp_lock);
- can_led_event(net, CAN_LED_EVENT_STOP);
-
return 0;
}
@@ -1177,7 +1172,6 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
break;
if (intf & CANINTF_TX) {
- can_led_event(net, CAN_LED_EVENT_TX);
if (priv->tx_busy) {
net->stats.tx_packets++;
net->stats.tx_bytes += can_get_echo_skb(net, 0,
@@ -1232,8 +1226,6 @@ static int mcp251x_open(struct net_device *net)
if (ret)
goto out_free_irq;
- can_led_event(net, CAN_LED_EVENT_OPEN);
-
netif_wake_queue(net);
mutex_unlock(&priv->mcp_lock);
@@ -1403,8 +1395,6 @@ static int mcp251x_can_probe(struct spi_device *spi)
if (ret)
goto error_probe;
- devm_can_led_init(net);
-
ret = mcp251x_gpio_setup(priv);
if (ret)
goto error_probe;
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index 1d43bccc29bf..2b0309fedfac 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -441,7 +441,7 @@ struct mcp251xfd_hw_tef_obj {
/* The tx_obj_raw version is used in spi async, i.e. without
* regmap. We have to take care of endianness ourselves.
*/
-struct mcp251xfd_hw_tx_obj_raw {
+struct __packed mcp251xfd_hw_tx_obj_raw {
__le32 id;
__le32 flags;
u8 data[sizeof_field(struct canfd_frame, data)];
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
index 25d6d81ab4f4..155b90f6c767 100644
--- a/drivers/net/can/sun4i_can.c
+++ b/drivers/net/can/sun4i_can.c
@@ -51,7 +51,6 @@
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -516,8 +515,6 @@ static void sun4i_can_rx(struct net_device *dev)
sun4i_can_write_cmdreg(priv, SUN4I_CMD_RELEASE_RBUF);
netif_rx(skb);
-
- can_led_event(dev, CAN_LED_EVENT_RX);
}
static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
@@ -664,7 +661,6 @@ static irqreturn_t sun4i_can_interrupt(int irq, void *dev_id)
stats->tx_bytes += can_get_echo_skb(dev, 0, NULL);
stats->tx_packets++;
netif_wake_queue(dev);
- can_led_event(dev, CAN_LED_EVENT_TX);
}
if ((isrc & SUN4I_INT_RBUF_VLD) &&
!(isrc & SUN4I_INT_DATA_OR)) {
@@ -729,7 +725,6 @@ static int sun4ican_open(struct net_device *dev)
goto exit_can_start;
}
- can_led_event(dev, CAN_LED_EVENT_OPEN);
netif_start_queue(dev);
return 0;
@@ -756,7 +751,6 @@ static int sun4ican_close(struct net_device *dev)
free_irq(dev->irq, dev);
close_candev(dev);
- can_led_event(dev, CAN_LED_EVENT_STOP);
return 0;
}
@@ -883,7 +877,6 @@ static int sun4ican_probe(struct platform_device *pdev)
DRV_NAME, err);
goto exit_free;
}
- devm_can_led_init(dev);
dev_info(&pdev->dev, "device registered (base=%p, irq=%d)\n",
priv->base, dev->irq);
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index bb3f2e3b004c..debe17bfd0f0 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -34,7 +34,6 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include <linux/can/rx-offload.h>
#define DRV_NAME "ti_hecc"
@@ -759,7 +758,6 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
can_rx_offload_get_echo_skb(&priv->offload,
mbxno, stamp, NULL);
stats->tx_packets++;
- can_led_event(ndev, CAN_LED_EVENT_TX);
--priv->tx_tail;
}
@@ -814,8 +812,6 @@ static int ti_hecc_open(struct net_device *ndev)
return err;
}
- can_led_event(ndev, CAN_LED_EVENT_OPEN);
-
ti_hecc_start(ndev);
can_rx_offload_enable(&priv->offload);
netif_start_queue(ndev);
@@ -834,8 +830,6 @@ static int ti_hecc_close(struct net_device *ndev)
close_candev(ndev);
ti_hecc_transceiver_switch(priv, 0);
- can_led_event(ndev, CAN_LED_EVENT_STOP);
-
return 0;
}
@@ -954,8 +948,6 @@ static int ti_hecc_probe(struct platform_device *pdev)
goto probe_exit_offload;
}
- devm_can_led_init(ndev);
-
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n",
priv->base, (u32)ndev->irq);
diff --git a/drivers/net/can/usb/mcba_usb.c b/drivers/net/can/usb/mcba_usb.c
index c45a814e1de2..792ab9da317d 100644
--- a/drivers/net/can/usb/mcba_usb.c
+++ b/drivers/net/can/usb/mcba_usb.c
@@ -10,7 +10,6 @@
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/signal.h>
@@ -232,8 +231,6 @@ static void mcba_usb_write_bulk_callback(struct urb *urb)
netdev->stats.tx_packets++;
netdev->stats.tx_bytes += can_get_echo_skb(netdev, ctx->ndx,
NULL);
-
- can_led_event(netdev, CAN_LED_EVENT_TX);
}
if (urb->status)
@@ -452,7 +449,6 @@ static void mcba_usb_process_can(struct mcba_priv *priv,
}
stats->rx_packets++;
- can_led_event(priv->netdev, CAN_LED_EVENT_RX);
netif_rx(skb);
}
@@ -700,7 +696,6 @@ static int mcba_usb_open(struct net_device *netdev)
priv->can_speed_check = true;
priv->can.state = CAN_STATE_ERROR_ACTIVE;
- can_led_event(netdev, CAN_LED_EVENT_OPEN);
netif_start_queue(netdev);
return 0;
@@ -732,7 +727,6 @@ static int mcba_usb_close(struct net_device *netdev)
mcba_urb_unlink(priv);
close_candev(netdev);
- can_led_event(netdev, CAN_LED_EVENT_STOP);
return 0;
}
@@ -857,8 +851,6 @@ static int mcba_usb_probe(struct usb_interface *intf,
priv->rx_pipe = usb_rcvbulkpipe(priv->udev, in->bEndpointAddress);
priv->tx_pipe = usb_sndbulkpipe(priv->udev, out->bEndpointAddress);
- devm_can_led_init(netdev);
-
/* Start USB dev only if we have successfully registered CAN device */
err = mcba_usb_start(priv);
if (err) {
diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c
index b638604bf1ee..f3363575bf32 100644
--- a/drivers/net/can/usb/usb_8dev.c
+++ b/drivers/net/can/usb/usb_8dev.c
@@ -21,7 +21,6 @@
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
/* driver constants */
#define MAX_RX_URBS 20
@@ -480,8 +479,6 @@ static void usb_8dev_rx_can_msg(struct usb_8dev_priv *priv,
stats->rx_packets++;
netif_rx(skb);
-
- can_led_event(priv->netdev, CAN_LED_EVENT_RX);
} else {
netdev_warn(priv->netdev, "frame type %d unknown",
msg->type);
@@ -582,8 +579,6 @@ static void usb_8dev_write_bulk_callback(struct urb *urb)
netdev->stats.tx_packets++;
netdev->stats.tx_bytes += can_get_echo_skb(netdev, context->echo_index, NULL);
- can_led_event(netdev, CAN_LED_EVENT_TX);
-
/* Release context */
context->echo_index = MAX_TX_URBS;
@@ -807,8 +802,6 @@ static int usb_8dev_open(struct net_device *netdev)
if (err)
return err;
- can_led_event(netdev, CAN_LED_EVENT_OPEN);
-
/* finally start device */
err = usb_8dev_start(priv);
if (err) {
@@ -865,8 +858,6 @@ static int usb_8dev_close(struct net_device *netdev)
close_candev(netdev);
- can_led_event(netdev, CAN_LED_EVENT_STOP);
-
return err;
}
@@ -974,8 +965,6 @@ static int usb_8dev_probe(struct usb_interface *intf,
(version>>8) & 0xff, version & 0xff);
}
- devm_can_led_init(netdev);
-
return 0;
cleanup_unregister_candev:
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 43f0c6a064ba..8a3b7b103ca4 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -26,7 +26,6 @@
#include <linux/types.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include <linux/pm_runtime.h>
#define DRIVER_NAME "xilinx_can"
@@ -1209,10 +1208,8 @@ static int xcan_rx_poll(struct napi_struct *napi, int quota)
XCAN_IXR_RXNEMP_MASK);
}
- if (work_done) {
- can_led_event(ndev, CAN_LED_EVENT_RX);
+ if (work_done)
xcan_update_error_state_after_rxtx(ndev);
- }
if (work_done < quota) {
if (napi_complete_done(napi, work_done)) {
@@ -1298,7 +1295,6 @@ static void xcan_tx_interrupt(struct net_device *ndev, u32 isr)
spin_unlock_irqrestore(&priv->tx_lock, flags);
- can_led_event(ndev, CAN_LED_EVENT_TX);
xcan_update_error_state_after_rxtx(ndev);
}
@@ -1420,7 +1416,6 @@ static int xcan_open(struct net_device *ndev)
goto err_candev;
}
- can_led_event(ndev, CAN_LED_EVENT_OPEN);
napi_enable(&priv->napi);
netif_start_queue(ndev);
@@ -1452,7 +1447,6 @@ static int xcan_close(struct net_device *ndev)
free_irq(ndev->irq, ndev);
close_candev(ndev);
- can_led_event(ndev, CAN_LED_EVENT_STOP);
pm_runtime_put(priv->dev);
return 0;
@@ -1804,7 +1798,7 @@ static int xcan_probe(struct platform_device *pdev)
priv->can.clock.freq = clk_get_rate(priv->can_clk);
- netif_napi_add(ndev, &priv->napi, xcan_rx_poll, rx_max);
+ netif_napi_add_weight(ndev, &priv->napi, xcan_rx_poll, rx_max);
ret = register_candev(ndev);
if (ret) {
@@ -1812,8 +1806,6 @@ static int xcan_probe(struct platform_device *pdev)
goto err_disableclks;
}
- devm_can_led_init(ndev);
-
pm_runtime_put(&pdev->dev);
if (priv->devtype.flags & XCAN_FLAG_CANFD_2) {
diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
index 12c15da55664..8af4def38a98 100644
--- a/drivers/net/dsa/lantiq_gswip.c
+++ b/drivers/net/dsa/lantiq_gswip.c
@@ -1360,7 +1360,7 @@ static int gswip_port_fdb(struct dsa_switch *ds, int port,
struct net_device *bridge = dsa_port_bridge_dev_get(dsa_to_port(ds, port));
struct gswip_priv *priv = ds->priv;
struct gswip_pce_table_entry mac_bridge = {0,};
- unsigned int cpu_port = priv->hw_info->cpu_port;
+ unsigned int max_ports = priv->hw_info->max_ports;
int fid = -1;
int i;
int err;
@@ -1368,7 +1368,7 @@ static int gswip_port_fdb(struct dsa_switch *ds, int port,
if (!bridge)
return -EINVAL;
- for (i = cpu_port; i < ARRAY_SIZE(priv->vlans); i++) {
+ for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) {
if (priv->vlans[i].bridge == bridge) {
fid = priv->vlans[i].fid;
break;
@@ -1426,8 +1426,9 @@ static int gswip_port_fdb_dump(struct dsa_switch *ds, int port,
err = gswip_pce_table_entry_read(priv, &mac_bridge);
if (err) {
- dev_err(priv->dev, "failed to write mac bridge: %d\n",
- err);
+ dev_err(priv->dev,
+ "failed to read mac bridge entry %d: %d\n",
+ i, err);
return err;
}
diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index f91deea9368e..12a599d5e61a 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -126,86 +126,6 @@ static u8 ksz8863_shifts[] = {
[DYNAMIC_MAC_SRC_PORT] = 20,
};
-struct mib_names {
- char string[ETH_GSTRING_LEN];
-};
-
-static const struct mib_names ksz87xx_mib_names[] = {
- { "rx_hi" },
- { "rx_undersize" },
- { "rx_fragments" },
- { "rx_oversize" },
- { "rx_jabbers" },
- { "rx_symbol_err" },
- { "rx_crc_err" },
- { "rx_align_err" },
- { "rx_mac_ctrl" },
- { "rx_pause" },
- { "rx_bcast" },
- { "rx_mcast" },
- { "rx_ucast" },
- { "rx_64_or_less" },
- { "rx_65_127" },
- { "rx_128_255" },
- { "rx_256_511" },
- { "rx_512_1023" },
- { "rx_1024_1522" },
- { "rx_1523_2000" },
- { "rx_2001" },
- { "tx_hi" },
- { "tx_late_col" },
- { "tx_pause" },
- { "tx_bcast" },
- { "tx_mcast" },
- { "tx_ucast" },
- { "tx_deferred" },
- { "tx_total_col" },
- { "tx_exc_col" },
- { "tx_single_col" },
- { "tx_mult_col" },
- { "rx_total" },
- { "tx_total" },
- { "rx_discards" },
- { "tx_discards" },
-};
-
-static const struct mib_names ksz88xx_mib_names[] = {
- { "rx" },
- { "rx_hi" },
- { "rx_undersize" },
- { "rx_fragments" },
- { "rx_oversize" },
- { "rx_jabbers" },
- { "rx_symbol_err" },
- { "rx_crc_err" },
- { "rx_align_err" },
- { "rx_mac_ctrl" },
- { "rx_pause" },
- { "rx_bcast" },
- { "rx_mcast" },
- { "rx_ucast" },
- { "rx_64_or_less" },
- { "rx_65_127" },
- { "rx_128_255" },
- { "rx_256_511" },
- { "rx_512_1023" },
- { "rx_1024_1522" },
- { "tx" },
- { "tx_hi" },
- { "tx_late_col" },
- { "tx_pause" },
- { "tx_bcast" },
- { "tx_mcast" },
- { "tx_ucast" },
- { "tx_deferred" },
- { "tx_total_col" },
- { "tx_exc_col" },
- { "tx_single_col" },
- { "tx_mult_col" },
- { "rx_discards" },
- { "tx_discards" },
-};
-
static bool ksz_is_ksz88x3(struct ksz_device *dev)
{
return dev->chip_id == 0x8830;
@@ -306,7 +226,7 @@ static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
masks = ksz8->masks;
regs = ksz8->regs;
- ctrl_addr = addr + dev->reg_mib_cnt * port;
+ ctrl_addr = addr + dev->info->reg_mib_cnt * port;
ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
mutex_lock(&dev->alu_mutex);
@@ -343,7 +263,7 @@ static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
masks = ksz8->masks;
regs = ksz8->regs;
- addr -= dev->reg_mib_cnt;
+ addr -= dev->info->reg_mib_cnt;
ctrl_addr = (KSZ8795_MIB_TOTAL_RX_1 - KSZ8795_MIB_TOTAL_RX_0) * port;
ctrl_addr += addr + KSZ8795_MIB_TOTAL_RX_0;
ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
@@ -392,7 +312,7 @@ static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
u32 data;
u32 cur;
- addr -= dev->reg_mib_cnt;
+ addr -= dev->info->reg_mib_cnt;
ctrl_addr = addr ? KSZ8863_MIB_PACKET_DROPPED_TX_0 :
KSZ8863_MIB_PACKET_DROPPED_RX_0;
ctrl_addr += port;
@@ -453,23 +373,21 @@ static void ksz8_port_init_cnt(struct ksz_device *dev, int port)
mib->cnt_ptr = 0;
/* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */
- while (mib->cnt_ptr < dev->reg_mib_cnt) {
+ while (mib->cnt_ptr < dev->info->reg_mib_cnt) {
dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr,
&mib->counters[mib->cnt_ptr]);
++mib->cnt_ptr;
}
/* last one in storage */
- dropped = &mib->counters[dev->mib_cnt];
+ dropped = &mib->counters[dev->info->mib_cnt];
/* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
- while (mib->cnt_ptr < dev->mib_cnt) {
+ while (mib->cnt_ptr < dev->info->mib_cnt) {
dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
dropped, &mib->counters[mib->cnt_ptr]);
++mib->cnt_ptr;
}
- mib->cnt_ptr = 0;
- memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
}
static void ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data)
@@ -1003,18 +921,6 @@ static u32 ksz8_sw_get_phy_flags(struct dsa_switch *ds, int port)
return 0;
}
-static void ksz8_get_strings(struct dsa_switch *ds, int port,
- u32 stringset, uint8_t *buf)
-{
- struct ksz_device *dev = ds->priv;
- int i;
-
- for (i = 0; i < dev->mib_cnt; i++) {
- memcpy(buf + i * ETH_GSTRING_LEN,
- dev->mib_names[i].string, ETH_GSTRING_LEN);
- }
-}
-
static void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
{
u8 data;
@@ -1036,13 +942,13 @@ static void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
int first, index, cnt;
struct ksz_port *p;
- if ((uint)port < dev->port_cnt) {
+ if ((uint)port < dev->info->port_cnt) {
first = port;
cnt = port + 1;
} else {
/* Flush all ports. */
first = 0;
- cnt = dev->port_cnt;
+ cnt = dev->info->port_cnt;
}
for (index = first; index < cnt; index++) {
p = &dev->ports[index];
@@ -1118,7 +1024,7 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
* Remove Tag flag to be changed, unless there are no
* other VLANs currently configured.
*/
- for (vid = 1; vid < dev->num_vlans; ++vid) {
+ for (vid = 1; vid < dev->info->num_vlans; ++vid) {
/* Skip the VID we are going to add or reconfigure */
if (vid == vlan->vid)
continue;
@@ -1389,7 +1295,7 @@ static int ksz8_handle_global_errata(struct dsa_switch *ds)
* KSZ879x/KSZ877x/KSZ876x and some EEE link partners may result in
* the link dropping.
*/
- if (dev->ksz87xx_eee_link_erratum)
+ if (dev->info->ksz87xx_eee_link_erratum)
ret = ksz8_ind_write8(dev, TABLE_EEE, REG_IND_EEE_GLOB2_HI, 0);
return ret;
@@ -1402,7 +1308,7 @@ static int ksz8_setup(struct dsa_switch *ds)
int i, ret = 0;
dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table),
- dev->num_vlans, GFP_KERNEL);
+ dev->info->num_vlans, GFP_KERNEL);
if (!dev->vlan_cache)
return -ENOMEM;
@@ -1446,7 +1352,7 @@ static int ksz8_setup(struct dsa_switch *ds)
(BROADCAST_STORM_VALUE *
BROADCAST_STORM_PROT_RATE) / 100);
- for (i = 0; i < (dev->num_vlans / 4); i++)
+ for (i = 0; i < (dev->info->num_vlans / 4); i++)
ksz8_r_vlan_entries(dev, i);
/* Setup STP address for STP operation. */
@@ -1454,7 +1360,7 @@ static int ksz8_setup(struct dsa_switch *ds)
ether_addr_copy(alu.mac, eth_stp_addr);
alu.is_static = true;
alu.is_override = true;
- alu.port_forward = dev->host_mask;
+ alu.port_forward = dev->info->cpu_ports;
ksz8_w_sta_mac_table(dev, 0, &alu);
@@ -1470,15 +1376,7 @@ static void ksz8_get_caps(struct dsa_switch *ds, int port,
{
struct ksz_device *dev = ds->priv;
- if (port == dev->cpu_port) {
- __set_bit(PHY_INTERFACE_MODE_RMII,
- config->supported_interfaces);
- __set_bit(PHY_INTERFACE_MODE_MII,
- config->supported_interfaces);
- } else {
- __set_bit(PHY_INTERFACE_MODE_INTERNAL,
- config->supported_interfaces);
- }
+ ksz_phylink_get_caps(ds, port, config);
config->mac_capabilities = MAC_10 | MAC_100;
@@ -1504,7 +1402,7 @@ static const struct dsa_switch_ops ksz8_switch_ops = {
.phylink_get_caps = ksz8_get_caps,
.phylink_mac_link_down = ksz_mac_link_down,
.port_enable = ksz_enable_port,
- .get_strings = ksz8_get_strings,
+ .get_strings = ksz_get_strings,
.get_ethtool_stats = ksz_get_ethtool_stats,
.get_sset_count = ksz_sset_count,
.port_bridge_join = ksz_port_bridge_join,
@@ -1571,140 +1469,26 @@ static int ksz8_switch_detect(struct ksz_device *dev)
return 0;
}
-struct ksz_chip_data {
- u16 chip_id;
- const char *dev_name;
- int num_vlans;
- int num_alus;
- int num_statics;
- int cpu_ports;
- int port_cnt;
- bool ksz87xx_eee_link_erratum;
-};
-
-static const struct ksz_chip_data ksz8_switch_chips[] = {
- {
- .chip_id = 0x8795,
- .dev_name = "KSZ8795",
- .num_vlans = 4096,
- .num_alus = 0,
- .num_statics = 8,
- .cpu_ports = 0x10, /* can be configured as cpu port */
- .port_cnt = 5, /* total cpu and user ports */
- .ksz87xx_eee_link_erratum = true,
- },
- {
- /*
- * WARNING
- * =======
- * KSZ8794 is similar to KSZ8795, except the port map
- * contains a gap between external and CPU ports, the
- * port map is NOT continuous. The per-port register
- * map is shifted accordingly too, i.e. registers at
- * offset 0x40 are NOT used on KSZ8794 and they ARE
- * used on KSZ8795 for external port 3.
- * external cpu
- * KSZ8794 0,1,2 4
- * KSZ8795 0,1,2,3 4
- * KSZ8765 0,1,2,3 4
- */
- .chip_id = 0x8794,
- .dev_name = "KSZ8794",
- .num_vlans = 4096,
- .num_alus = 0,
- .num_statics = 8,
- .cpu_ports = 0x10, /* can be configured as cpu port */
- .port_cnt = 4, /* total cpu and user ports */
- .ksz87xx_eee_link_erratum = true,
- },
- {
- .chip_id = 0x8765,
- .dev_name = "KSZ8765",
- .num_vlans = 4096,
- .num_alus = 0,
- .num_statics = 8,
- .cpu_ports = 0x10, /* can be configured as cpu port */
- .port_cnt = 5, /* total cpu and user ports */
- .ksz87xx_eee_link_erratum = true,
- },
- {
- .chip_id = 0x8830,
- .dev_name = "KSZ8863/KSZ8873",
- .num_vlans = 16,
- .num_alus = 0,
- .num_statics = 8,
- .cpu_ports = 0x4, /* can be configured as cpu port */
- .port_cnt = 3,
- },
-};
-
static int ksz8_switch_init(struct ksz_device *dev)
{
struct ksz8 *ksz8 = dev->priv;
- int i;
dev->ds->ops = &ksz8_switch_ops;
- for (i = 0; i < ARRAY_SIZE(ksz8_switch_chips); i++) {
- const struct ksz_chip_data *chip = &ksz8_switch_chips[i];
-
- if (dev->chip_id == chip->chip_id) {
- dev->name = chip->dev_name;
- dev->num_vlans = chip->num_vlans;
- dev->num_alus = chip->num_alus;
- dev->num_statics = chip->num_statics;
- dev->port_cnt = fls(chip->cpu_ports);
- dev->cpu_port = fls(chip->cpu_ports) - 1;
- dev->phy_port_cnt = dev->port_cnt - 1;
- dev->cpu_ports = chip->cpu_ports;
- dev->host_mask = chip->cpu_ports;
- dev->port_mask = (BIT(dev->phy_port_cnt) - 1) |
- chip->cpu_ports;
- dev->ksz87xx_eee_link_erratum =
- chip->ksz87xx_eee_link_erratum;
- break;
- }
- }
-
- /* no switch found */
- if (!dev->cpu_ports)
- return -ENODEV;
+ dev->cpu_port = fls(dev->info->cpu_ports) - 1;
+ dev->phy_port_cnt = dev->info->port_cnt - 1;
+ dev->port_mask = (BIT(dev->phy_port_cnt) - 1) | dev->info->cpu_ports;
if (ksz_is_ksz88x3(dev)) {
ksz8->regs = ksz8863_regs;
ksz8->masks = ksz8863_masks;
ksz8->shifts = ksz8863_shifts;
- dev->mib_cnt = ARRAY_SIZE(ksz88xx_mib_names);
- dev->mib_names = ksz88xx_mib_names;
} else {
ksz8->regs = ksz8795_regs;
ksz8->masks = ksz8795_masks;
ksz8->shifts = ksz8795_shifts;
- dev->mib_cnt = ARRAY_SIZE(ksz87xx_mib_names);
- dev->mib_names = ksz87xx_mib_names;
- }
-
- dev->reg_mib_cnt = MIB_COUNTER_NUM;
-
- dev->ports = devm_kzalloc(dev->dev,
- dev->port_cnt * sizeof(struct ksz_port),
- GFP_KERNEL);
- if (!dev->ports)
- return -ENOMEM;
- for (i = 0; i < dev->port_cnt; i++) {
- mutex_init(&dev->ports[i].mib.cnt_mutex);
- dev->ports[i].mib.counters =
- devm_kzalloc(dev->dev,
- sizeof(u64) *
- (dev->mib_cnt + 1),
- GFP_KERNEL);
- if (!dev->ports[i].mib.counters)
- return -ENOMEM;
}
- /* set the real number of ports */
- dev->ds->num_ports = dev->port_cnt;
-
/* We rely on software untagging on the CPU port, so that we
* can support both tagged and untagged VLANs
*/
diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c
index 5f8d94aee774..961a74c359a8 100644
--- a/drivers/net/dsa/microchip/ksz8795_spi.c
+++ b/drivers/net/dsa/microchip/ksz8795_spi.c
@@ -34,6 +34,7 @@ KSZ_REGMAP_TABLE(ksz8863, 16, KSZ8863_SPI_ADDR_SHIFT,
static int ksz8795_spi_probe(struct spi_device *spi)
{
const struct regmap_config *regmap_config;
+ const struct ksz_chip_data *chip;
struct device *ddev = &spi->dev;
struct regmap_config rc;
struct ksz_device *dev;
@@ -50,10 +51,15 @@ static int ksz8795_spi_probe(struct spi_device *spi)
if (!dev)
return -ENOMEM;
- regmap_config = device_get_match_data(ddev);
- if (!regmap_config)
+ chip = device_get_match_data(ddev);
+ if (!chip)
return -EINVAL;
+ if (chip->chip_id == KSZ8830_CHIP_ID)
+ regmap_config = ksz8863_regmap_config;
+ else
+ regmap_config = ksz8795_regmap_config;
+
for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
rc = regmap_config[i];
rc.lock_arg = &dev->regmap_mutex;
@@ -113,11 +119,26 @@ static void ksz8795_spi_shutdown(struct spi_device *spi)
}
static const struct of_device_id ksz8795_dt_ids[] = {
- { .compatible = "microchip,ksz8765", .data = &ksz8795_regmap_config },
- { .compatible = "microchip,ksz8794", .data = &ksz8795_regmap_config },
- { .compatible = "microchip,ksz8795", .data = &ksz8795_regmap_config },
- { .compatible = "microchip,ksz8863", .data = &ksz8863_regmap_config },
- { .compatible = "microchip,ksz8873", .data = &ksz8863_regmap_config },
+ {
+ .compatible = "microchip,ksz8765",
+ .data = &ksz_switch_chips[KSZ8765]
+ },
+ {
+ .compatible = "microchip,ksz8794",
+ .data = &ksz_switch_chips[KSZ8794]
+ },
+ {
+ .compatible = "microchip,ksz8795",
+ .data = &ksz_switch_chips[KSZ8795]
+ },
+ {
+ .compatible = "microchip,ksz8863",
+ .data = &ksz_switch_chips[KSZ8830]
+ },
+ {
+ .compatible = "microchip,ksz8873",
+ .data = &ksz_switch_chips[KSZ8830]
+ },
{},
};
MODULE_DEVICE_TABLE(of, ksz8795_dt_ids);
diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c
index 5883fa7edda2..b6f99e641dca 100644
--- a/drivers/net/dsa/microchip/ksz8863_smi.c
+++ b/drivers/net/dsa/microchip/ksz8863_smi.c
@@ -206,8 +206,14 @@ static void ksz8863_smi_shutdown(struct mdio_device *mdiodev)
}
static const struct of_device_id ksz8863_dt_ids[] = {
- { .compatible = "microchip,ksz8863" },
- { .compatible = "microchip,ksz8873" },
+ {
+ .compatible = "microchip,ksz8863",
+ .data = &ksz_switch_chips[KSZ8830]
+ },
+ {
+ .compatible = "microchip,ksz8873",
+ .data = &ksz_switch_chips[KSZ8830]
+ },
{ },
};
MODULE_DEVICE_TABLE(of, ksz8863_dt_ids);
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index 61dd0fa97748..ab40b700cf1a 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -23,48 +23,6 @@
#define NEW_XMII BIT(1)
#define IS_9893 BIT(2)
-static const struct {
- int index;
- char string[ETH_GSTRING_LEN];
-} ksz9477_mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
- { 0x00, "rx_hi" },
- { 0x01, "rx_undersize" },
- { 0x02, "rx_fragments" },
- { 0x03, "rx_oversize" },
- { 0x04, "rx_jabbers" },
- { 0x05, "rx_symbol_err" },
- { 0x06, "rx_crc_err" },
- { 0x07, "rx_align_err" },
- { 0x08, "rx_mac_ctrl" },
- { 0x09, "rx_pause" },
- { 0x0A, "rx_bcast" },
- { 0x0B, "rx_mcast" },
- { 0x0C, "rx_ucast" },
- { 0x0D, "rx_64_or_less" },
- { 0x0E, "rx_65_127" },
- { 0x0F, "rx_128_255" },
- { 0x10, "rx_256_511" },
- { 0x11, "rx_512_1023" },
- { 0x12, "rx_1024_1522" },
- { 0x13, "rx_1523_2000" },
- { 0x14, "rx_2001" },
- { 0x15, "tx_hi" },
- { 0x16, "tx_late_col" },
- { 0x17, "tx_pause" },
- { 0x18, "tx_bcast" },
- { 0x19, "tx_mcast" },
- { 0x1A, "tx_ucast" },
- { 0x1B, "tx_deferred" },
- { 0x1C, "tx_total_col" },
- { 0x1D, "tx_exc_col" },
- { 0x1E, "tx_single_col" },
- { 0x1F, "tx_mult_col" },
- { 0x80, "rx_total" },
- { 0x81, "tx_total" },
- { 0x82, "rx_discards" },
- { 0x83, "tx_discards" },
-};
-
static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
@@ -100,7 +58,7 @@ static int ksz9477_change_mtu(struct dsa_switch *ds, int port, int mtu)
/* Cache the per-port MTU setting */
dev->ports[port].max_frame = frame_size;
- for (i = 0; i < dev->port_cnt; i++)
+ for (i = 0; i < dev->info->port_cnt; i++)
max_frame = max(max_frame, dev->ports[i].max_frame);
return regmap_update_bits(dev->regmap[1], REG_SW_MTU__2,
@@ -287,7 +245,7 @@ static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
static void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
u64 *dropped, u64 *cnt)
{
- addr = ksz9477_mib_names[addr].index;
+ addr = dev->info->mib_names[addr].index;
ksz9477_r_mib_cnt(dev, port, addr, cnt);
}
@@ -316,9 +274,6 @@ static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH);
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0);
mutex_unlock(&mib->cnt_mutex);
-
- mib->cnt_ptr = 0;
- memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
}
static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
@@ -400,20 +355,6 @@ static int ksz9477_phy_write16(struct dsa_switch *ds, int addr, int reg,
return 0;
}
-static void ksz9477_get_strings(struct dsa_switch *ds, int port,
- u32 stringset, uint8_t *buf)
-{
- int i;
-
- if (stringset != ETH_SS_STATS)
- return;
-
- for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
- memcpy(buf + i * ETH_GSTRING_LEN, ksz9477_mib_names[i].string,
- ETH_GSTRING_LEN);
- }
-}
-
static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
u8 member)
{
@@ -434,7 +375,7 @@ static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S,
SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S);
- if (port < dev->port_cnt) {
+ if (port < dev->info->port_cnt) {
/* flush individual port */
ksz_pread8(dev, port, P_STP_CTRL, &data);
if (!(data & PORT_LEARN_DISABLE))
@@ -756,7 +697,7 @@ static int ksz9477_port_mdb_add(struct dsa_switch *ds, int port,
mutex_lock(&dev->alu_mutex);
- for (index = 0; index < dev->num_statics; index++) {
+ for (index = 0; index < dev->info->num_statics; index++) {
/* find empty slot first */
data = (index << ALU_STAT_INDEX_S) |
ALU_STAT_READ | ALU_STAT_START;
@@ -787,7 +728,7 @@ static int ksz9477_port_mdb_add(struct dsa_switch *ds, int port,
}
/* no available entry */
- if (index == dev->num_statics) {
+ if (index == dev->info->num_statics) {
err = -ENOSPC;
goto exit;
}
@@ -832,7 +773,7 @@ static int ksz9477_port_mdb_del(struct dsa_switch *ds, int port,
mutex_lock(&dev->alu_mutex);
- for (index = 0; index < dev->num_statics; index++) {
+ for (index = 0; index < dev->info->num_statics; index++) {
/* find empty slot first */
data = (index << ALU_STAT_INDEX_S) |
ALU_STAT_READ | ALU_STAT_START;
@@ -861,7 +802,7 @@ static int ksz9477_port_mdb_del(struct dsa_switch *ds, int port,
}
/* no available entry */
- if (index == dev->num_statics)
+ if (index == dev->info->num_statics)
goto exit;
/* clear port */
@@ -903,7 +844,7 @@ static int ksz9477_port_mirror_add(struct dsa_switch *ds, int port,
* Check if any of the port is already set for sniffing
* If yes, instruct the user to remove the previous entry & exit
*/
- for (p = 0; p < dev->port_cnt; p++) {
+ for (p = 0; p < dev->info->port_cnt; p++) {
/* Skip the current sniffing port */
if (p == mirror->to_local_port)
continue;
@@ -946,7 +887,7 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
/* Check if any of the port is still referring to sniffer port */
- for (p = 0; p < dev->port_cnt; p++) {
+ for (p = 0; p < dev->info->port_cnt; p++) {
ksz_pread8(dev, p, P_MIRROR_CTRL, &data);
if ((data & (PORT_MIRROR_RX | PORT_MIRROR_TX))) {
@@ -1156,6 +1097,15 @@ static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
}
+static void ksz9477_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config)
+{
+ ksz_phylink_get_caps(ds, port, config);
+
+ config->mac_capabilities = MAC_10 | MAC_100 | MAC_1000FD |
+ MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
+}
+
static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{
struct ksz_port *p = &dev->ports[port];
@@ -1194,7 +1144,7 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
false);
- if (dev->phy_errata_9477)
+ if (dev->info->phy_errata_9477)
ksz9477_phy_errata_setup(dev, port);
} else {
/* force flow control */
@@ -1259,8 +1209,9 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds)
struct ksz_port *p;
int i;
- for (i = 0; i < dev->port_cnt; i++) {
- if (dsa_is_cpu_port(ds, i) && (dev->cpu_ports & (1 << i))) {
+ for (i = 0; i < dev->info->port_cnt; i++) {
+ if (dsa_is_cpu_port(ds, i) &&
+ (dev->info->cpu_ports & (1 << i))) {
phy_interface_t interface;
const char *prev_msg;
const char *prev_mode;
@@ -1304,7 +1255,7 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds)
}
}
- for (i = 0; i < dev->port_cnt; i++) {
+ for (i = 0; i < dev->info->port_cnt; i++) {
if (i == dev->cpu_port)
continue;
p = &dev->ports[i];
@@ -1328,7 +1279,7 @@ static int ksz9477_setup(struct dsa_switch *ds)
int ret = 0;
dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table),
- dev->num_vlans, GFP_KERNEL);
+ dev->info->num_vlans, GFP_KERNEL);
if (!dev->vlan_cache)
return -ENOMEM;
@@ -1380,8 +1331,9 @@ static const struct dsa_switch_ops ksz9477_switch_ops = {
.phy_read = ksz9477_phy_read16,
.phy_write = ksz9477_phy_write16,
.phylink_mac_link_down = ksz_mac_link_down,
+ .phylink_get_caps = ksz9477_get_caps,
.port_enable = ksz_enable_port,
- .get_strings = ksz9477_get_strings,
+ .get_strings = ksz_get_strings,
.get_ethtool_stats = ksz_get_ethtool_stats,
.get_sset_count = ksz_sset_count,
.port_bridge_join = ksz_port_bridge_join,
@@ -1470,109 +1422,11 @@ static int ksz9477_switch_detect(struct ksz_device *dev)
return 0;
}
-struct ksz_chip_data {
- u32 chip_id;
- const char *dev_name;
- int num_vlans;
- int num_alus;
- int num_statics;
- int cpu_ports;
- int port_cnt;
- bool phy_errata_9477;
-};
-
-static const struct ksz_chip_data ksz9477_switch_chips[] = {
- {
- .chip_id = 0x00947700,
- .dev_name = "KSZ9477",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x7F, /* can be configured as cpu port */
- .port_cnt = 7, /* total physical port count */
- .phy_errata_9477 = true,
- },
- {
- .chip_id = 0x00989700,
- .dev_name = "KSZ9897",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x7F, /* can be configured as cpu port */
- .port_cnt = 7, /* total physical port count */
- .phy_errata_9477 = true,
- },
- {
- .chip_id = 0x00989300,
- .dev_name = "KSZ9893",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x07, /* can be configured as cpu port */
- .port_cnt = 3, /* total port count */
- },
- {
- .chip_id = 0x00956700,
- .dev_name = "KSZ9567",
- .num_vlans = 4096,
- .num_alus = 4096,
- .num_statics = 16,
- .cpu_ports = 0x7F, /* can be configured as cpu port */
- .port_cnt = 7, /* total physical port count */
- .phy_errata_9477 = true,
- },
-};
-
static int ksz9477_switch_init(struct ksz_device *dev)
{
- int i;
-
dev->ds->ops = &ksz9477_switch_ops;
- for (i = 0; i < ARRAY_SIZE(ksz9477_switch_chips); i++) {
- const struct ksz_chip_data *chip = &ksz9477_switch_chips[i];
-
- if (dev->chip_id == chip->chip_id) {
- dev->name = chip->dev_name;
- dev->num_vlans = chip->num_vlans;
- dev->num_alus = chip->num_alus;
- dev->num_statics = chip->num_statics;
- dev->port_cnt = chip->port_cnt;
- dev->cpu_ports = chip->cpu_ports;
- dev->phy_errata_9477 = chip->phy_errata_9477;
-
- break;
- }
- }
-
- /* no switch found */
- if (!dev->port_cnt)
- return -ENODEV;
-
- dev->port_mask = (1 << dev->port_cnt) - 1;
-
- dev->reg_mib_cnt = SWITCH_COUNTER_NUM;
- dev->mib_cnt = TOTAL_SWITCH_COUNTER_NUM;
-
- dev->ports = devm_kzalloc(dev->dev,
- dev->port_cnt * sizeof(struct ksz_port),
- GFP_KERNEL);
- if (!dev->ports)
- return -ENOMEM;
- for (i = 0; i < dev->port_cnt; i++) {
- spin_lock_init(&dev->ports[i].mib.stats64_lock);
- mutex_init(&dev->ports[i].mib.cnt_mutex);
- dev->ports[i].mib.counters =
- devm_kzalloc(dev->dev,
- sizeof(u64) *
- (TOTAL_SWITCH_COUNTER_NUM + 1),
- GFP_KERNEL);
- if (!dev->ports[i].mib.counters)
- return -ENOMEM;
- }
-
- /* set the real number of ports */
- dev->ds->num_ports = dev->port_cnt;
+ dev->port_mask = (1 << dev->info->port_cnt) - 1;
return 0;
}
diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c
index cbc0b20e7e1b..faa3163c86b0 100644
--- a/drivers/net/dsa/microchip/ksz9477_i2c.c
+++ b/drivers/net/dsa/microchip/ksz9477_i2c.c
@@ -87,12 +87,30 @@ static const struct i2c_device_id ksz9477_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, ksz9477_i2c_id);
static const struct of_device_id ksz9477_dt_ids[] = {
- { .compatible = "microchip,ksz9477" },
- { .compatible = "microchip,ksz9897" },
- { .compatible = "microchip,ksz9893" },
- { .compatible = "microchip,ksz9563" },
- { .compatible = "microchip,ksz9567" },
- { .compatible = "microchip,ksz8563" },
+ {
+ .compatible = "microchip,ksz9477",
+ .data = &ksz_switch_chips[KSZ9477]
+ },
+ {
+ .compatible = "microchip,ksz9897",
+ .data = &ksz_switch_chips[KSZ9897]
+ },
+ {
+ .compatible = "microchip,ksz9893",
+ .data = &ksz_switch_chips[KSZ9893]
+ },
+ {
+ .compatible = "microchip,ksz9563",
+ .data = &ksz_switch_chips[KSZ9893]
+ },
+ {
+ .compatible = "microchip,ksz8563",
+ .data = &ksz_switch_chips[KSZ9893]
+ },
+ {
+ .compatible = "microchip,ksz9567",
+ .data = &ksz_switch_chips[KSZ9567]
+ },
{},
};
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c
index 87ca464dad32..1bc8b0cbe458 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -86,12 +86,30 @@ static void ksz9477_spi_shutdown(struct spi_device *spi)
}
static const struct of_device_id ksz9477_dt_ids[] = {
- { .compatible = "microchip,ksz9477" },
- { .compatible = "microchip,ksz9897" },
- { .compatible = "microchip,ksz9893" },
- { .compatible = "microchip,ksz9563" },
- { .compatible = "microchip,ksz8563" },
- { .compatible = "microchip,ksz9567" },
+ {
+ .compatible = "microchip,ksz9477",
+ .data = &ksz_switch_chips[KSZ9477]
+ },
+ {
+ .compatible = "microchip,ksz9897",
+ .data = &ksz_switch_chips[KSZ9897]
+ },
+ {
+ .compatible = "microchip,ksz9893",
+ .data = &ksz_switch_chips[KSZ9893]
+ },
+ {
+ .compatible = "microchip,ksz9563",
+ .data = &ksz_switch_chips[KSZ9893]
+ },
+ {
+ .compatible = "microchip,ksz8563",
+ .data = &ksz_switch_chips[KSZ9893]
+ },
+ {
+ .compatible = "microchip,ksz9567",
+ .data = &ksz_switch_chips[KSZ9567]
+ },
{},
};
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 10f127b09e58..9ca8c8d7740f 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -14,12 +14,15 @@
#include <linux/phy.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
+#include <linux/of_device.h>
#include <linux/of_net.h>
#include <net/dsa.h>
#include <net/switchdev.h>
#include "ksz_common.h"
+#define MIB_COUNTER_NUM 0x20
+
struct ksz_stats_raw {
u64 rx_hi;
u64 rx_undersize;
@@ -59,6 +62,403 @@ struct ksz_stats_raw {
u64 tx_discards;
};
+static const struct ksz_mib_names ksz88xx_mib_names[] = {
+ { 0x00, "rx" },
+ { 0x01, "rx_hi" },
+ { 0x02, "rx_undersize" },
+ { 0x03, "rx_fragments" },
+ { 0x04, "rx_oversize" },
+ { 0x05, "rx_jabbers" },
+ { 0x06, "rx_symbol_err" },
+ { 0x07, "rx_crc_err" },
+ { 0x08, "rx_align_err" },
+ { 0x09, "rx_mac_ctrl" },
+ { 0x0a, "rx_pause" },
+ { 0x0b, "rx_bcast" },
+ { 0x0c, "rx_mcast" },
+ { 0x0d, "rx_ucast" },
+ { 0x0e, "rx_64_or_less" },
+ { 0x0f, "rx_65_127" },
+ { 0x10, "rx_128_255" },
+ { 0x11, "rx_256_511" },
+ { 0x12, "rx_512_1023" },
+ { 0x13, "rx_1024_1522" },
+ { 0x14, "tx" },
+ { 0x15, "tx_hi" },
+ { 0x16, "tx_late_col" },
+ { 0x17, "tx_pause" },
+ { 0x18, "tx_bcast" },
+ { 0x19, "tx_mcast" },
+ { 0x1a, "tx_ucast" },
+ { 0x1b, "tx_deferred" },
+ { 0x1c, "tx_total_col" },
+ { 0x1d, "tx_exc_col" },
+ { 0x1e, "tx_single_col" },
+ { 0x1f, "tx_mult_col" },
+ { 0x100, "rx_discards" },
+ { 0x101, "tx_discards" },
+};
+
+static const struct ksz_mib_names ksz9477_mib_names[] = {
+ { 0x00, "rx_hi" },
+ { 0x01, "rx_undersize" },
+ { 0x02, "rx_fragments" },
+ { 0x03, "rx_oversize" },
+ { 0x04, "rx_jabbers" },
+ { 0x05, "rx_symbol_err" },
+ { 0x06, "rx_crc_err" },
+ { 0x07, "rx_align_err" },
+ { 0x08, "rx_mac_ctrl" },
+ { 0x09, "rx_pause" },
+ { 0x0A, "rx_bcast" },
+ { 0x0B, "rx_mcast" },
+ { 0x0C, "rx_ucast" },
+ { 0x0D, "rx_64_or_less" },
+ { 0x0E, "rx_65_127" },
+ { 0x0F, "rx_128_255" },
+ { 0x10, "rx_256_511" },
+ { 0x11, "rx_512_1023" },
+ { 0x12, "rx_1024_1522" },
+ { 0x13, "rx_1523_2000" },
+ { 0x14, "rx_2001" },
+ { 0x15, "tx_hi" },
+ { 0x16, "tx_late_col" },
+ { 0x17, "tx_pause" },
+ { 0x18, "tx_bcast" },
+ { 0x19, "tx_mcast" },
+ { 0x1A, "tx_ucast" },
+ { 0x1B, "tx_deferred" },
+ { 0x1C, "tx_total_col" },
+ { 0x1D, "tx_exc_col" },
+ { 0x1E, "tx_single_col" },
+ { 0x1F, "tx_mult_col" },
+ { 0x80, "rx_total" },
+ { 0x81, "tx_total" },
+ { 0x82, "rx_discards" },
+ { 0x83, "tx_discards" },
+};
+
+const struct ksz_chip_data ksz_switch_chips[] = {
+ [KSZ8795] = {
+ .chip_id = KSZ8795_CHIP_ID,
+ .dev_name = "KSZ8795",
+ .num_vlans = 4096,
+ .num_alus = 0,
+ .num_statics = 8,
+ .cpu_ports = 0x10, /* can be configured as cpu port */
+ .port_cnt = 5, /* total cpu and user ports */
+ .ksz87xx_eee_link_erratum = true,
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false, true},
+ .supports_rmii = {false, false, false, false, true},
+ .supports_rgmii = {false, false, false, false, true},
+ .internal_phy = {true, true, true, true, false},
+ },
+
+ [KSZ8794] = {
+ /* WARNING
+ * =======
+ * KSZ8794 is similar to KSZ8795, except the port map
+ * contains a gap between external and CPU ports, the
+ * port map is NOT continuous. The per-port register
+ * map is shifted accordingly too, i.e. registers at
+ * offset 0x40 are NOT used on KSZ8794 and they ARE
+ * used on KSZ8795 for external port 3.
+ * external cpu
+ * KSZ8794 0,1,2 4
+ * KSZ8795 0,1,2,3 4
+ * KSZ8765 0,1,2,3 4
+ * port_cnt is configured as 5, even though it is 4
+ */
+ .chip_id = KSZ8794_CHIP_ID,
+ .dev_name = "KSZ8794",
+ .num_vlans = 4096,
+ .num_alus = 0,
+ .num_statics = 8,
+ .cpu_ports = 0x10, /* can be configured as cpu port */
+ .port_cnt = 5, /* total cpu and user ports */
+ .ksz87xx_eee_link_erratum = true,
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false, true},
+ .supports_rmii = {false, false, false, false, true},
+ .supports_rgmii = {false, false, false, false, true},
+ .internal_phy = {true, true, true, false, false},
+ },
+
+ [KSZ8765] = {
+ .chip_id = KSZ8765_CHIP_ID,
+ .dev_name = "KSZ8765",
+ .num_vlans = 4096,
+ .num_alus = 0,
+ .num_statics = 8,
+ .cpu_ports = 0x10, /* can be configured as cpu port */
+ .port_cnt = 5, /* total cpu and user ports */
+ .ksz87xx_eee_link_erratum = true,
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false, true},
+ .supports_rmii = {false, false, false, false, true},
+ .supports_rgmii = {false, false, false, false, true},
+ .internal_phy = {true, true, true, true, false},
+ },
+
+ [KSZ8830] = {
+ .chip_id = KSZ8830_CHIP_ID,
+ .dev_name = "KSZ8863/KSZ8873",
+ .num_vlans = 16,
+ .num_alus = 0,
+ .num_statics = 8,
+ .cpu_ports = 0x4, /* can be configured as cpu port */
+ .port_cnt = 3,
+ .mib_names = ksz88xx_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, true},
+ .supports_rmii = {false, false, true},
+ .internal_phy = {true, true, false},
+ },
+
+ [KSZ9477] = {
+ .chip_id = KSZ9477_CHIP_ID,
+ .dev_name = "KSZ9477",
+ .num_vlans = 4096,
+ .num_alus = 4096,
+ .num_statics = 16,
+ .cpu_ports = 0x7F, /* can be configured as cpu port */
+ .port_cnt = 7, /* total physical port count */
+ .phy_errata_9477 = true,
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false,
+ false, true, false},
+ .supports_rmii = {false, false, false, false,
+ false, true, false},
+ .supports_rgmii = {false, false, false, false,
+ false, true, false},
+ .internal_phy = {true, true, true, true,
+ true, false, false},
+ },
+
+ [KSZ9897] = {
+ .chip_id = KSZ9897_CHIP_ID,
+ .dev_name = "KSZ9897",
+ .num_vlans = 4096,
+ .num_alus = 4096,
+ .num_statics = 16,
+ .cpu_ports = 0x7F, /* can be configured as cpu port */
+ .port_cnt = 7, /* total physical port count */
+ .phy_errata_9477 = true,
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false,
+ false, true, true},
+ .supports_rmii = {false, false, false, false,
+ false, true, true},
+ .supports_rgmii = {false, false, false, false,
+ false, true, true},
+ .internal_phy = {true, true, true, true,
+ true, false, false},
+ },
+
+ [KSZ9893] = {
+ .chip_id = KSZ9893_CHIP_ID,
+ .dev_name = "KSZ9893",
+ .num_vlans = 4096,
+ .num_alus = 4096,
+ .num_statics = 16,
+ .cpu_ports = 0x07, /* can be configured as cpu port */
+ .port_cnt = 3, /* total port count */
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, true},
+ .supports_rmii = {false, false, true},
+ .supports_rgmii = {false, false, true},
+ .internal_phy = {true, true, false},
+ },
+
+ [KSZ9567] = {
+ .chip_id = KSZ9567_CHIP_ID,
+ .dev_name = "KSZ9567",
+ .num_vlans = 4096,
+ .num_alus = 4096,
+ .num_statics = 16,
+ .cpu_ports = 0x7F, /* can be configured as cpu port */
+ .port_cnt = 7, /* total physical port count */
+ .phy_errata_9477 = true,
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false,
+ false, true, true},
+ .supports_rmii = {false, false, false, false,
+ false, true, true},
+ .supports_rgmii = {false, false, false, false,
+ false, true, true},
+ .internal_phy = {true, true, true, true,
+ true, false, false},
+ },
+
+ [LAN9370] = {
+ .chip_id = LAN9370_CHIP_ID,
+ .dev_name = "LAN9370",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ .cpu_ports = 0x10, /* can be configured as cpu port */
+ .port_cnt = 5, /* total physical port count */
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false, true},
+ .supports_rmii = {false, false, false, false, true},
+ .supports_rgmii = {false, false, false, false, true},
+ .internal_phy = {true, true, true, true, false},
+ },
+
+ [LAN9371] = {
+ .chip_id = LAN9371_CHIP_ID,
+ .dev_name = "LAN9371",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ .cpu_ports = 0x30, /* can be configured as cpu port */
+ .port_cnt = 6, /* total physical port count */
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false, true, true},
+ .supports_rmii = {false, false, false, false, true, true},
+ .supports_rgmii = {false, false, false, false, true, true},
+ .internal_phy = {true, true, true, true, false, false},
+ },
+
+ [LAN9372] = {
+ .chip_id = LAN9372_CHIP_ID,
+ .dev_name = "LAN9372",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ .cpu_ports = 0x30, /* can be configured as cpu port */
+ .port_cnt = 8, /* total physical port count */
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false,
+ true, true, false, false},
+ .supports_rmii = {false, false, false, false,
+ true, true, false, false},
+ .supports_rgmii = {false, false, false, false,
+ true, true, false, false},
+ .internal_phy = {true, true, true, true,
+ false, false, true, true},
+ },
+
+ [LAN9373] = {
+ .chip_id = LAN9373_CHIP_ID,
+ .dev_name = "LAN9373",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ .cpu_ports = 0x38, /* can be configured as cpu port */
+ .port_cnt = 5, /* total physical port count */
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false,
+ true, true, false, false},
+ .supports_rmii = {false, false, false, false,
+ true, true, false, false},
+ .supports_rgmii = {false, false, false, false,
+ true, true, false, false},
+ .internal_phy = {true, true, true, false,
+ false, false, true, true},
+ },
+
+ [LAN9374] = {
+ .chip_id = LAN9374_CHIP_ID,
+ .dev_name = "LAN9374",
+ .num_vlans = 4096,
+ .num_alus = 1024,
+ .num_statics = 256,
+ .cpu_ports = 0x30, /* can be configured as cpu port */
+ .port_cnt = 8, /* total physical port count */
+ .mib_names = ksz9477_mib_names,
+ .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+ .reg_mib_cnt = MIB_COUNTER_NUM,
+ .supports_mii = {false, false, false, false,
+ true, true, false, false},
+ .supports_rmii = {false, false, false, false,
+ true, true, false, false},
+ .supports_rgmii = {false, false, false, false,
+ true, true, false, false},
+ .internal_phy = {true, true, true, true,
+ false, false, true, true},
+ },
+};
+EXPORT_SYMBOL_GPL(ksz_switch_chips);
+
+static const struct ksz_chip_data *ksz_lookup_info(unsigned int prod_num)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ksz_switch_chips); i++) {
+ const struct ksz_chip_data *chip = &ksz_switch_chips[i];
+
+ if (chip->chip_id == prod_num)
+ return chip;
+ }
+
+ return NULL;
+}
+
+static int ksz_check_device_id(struct ksz_device *dev)
+{
+ const struct ksz_chip_data *dt_chip_data;
+
+ dt_chip_data = of_device_get_match_data(dev->dev);
+
+ /* Check for Device Tree and Chip ID */
+ if (dt_chip_data->chip_id != dev->chip_id) {
+ dev_err(dev->dev,
+ "Device tree specifies chip %s but found %s, please fix it!\n",
+ dt_chip_data->dev_name, dev->info->dev_name);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config)
+{
+ struct ksz_device *dev = ds->priv;
+
+ config->legacy_pre_march2020 = false;
+
+ if (dev->info->supports_mii[port])
+ __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces);
+
+ if (dev->info->supports_rmii[port])
+ __set_bit(PHY_INTERFACE_MODE_RMII,
+ config->supported_interfaces);
+
+ if (dev->info->supports_rgmii[port])
+ phy_interface_set_rgmii(config->supported_interfaces);
+
+ if (dev->info->internal_phy[port])
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ config->supported_interfaces);
+}
+EXPORT_SYMBOL_GPL(ksz_phylink_get_caps);
+
void ksz_r_mib_stats64(struct ksz_device *dev, int port)
{
struct rtnl_link_stats64 *stats;
@@ -116,6 +516,22 @@ void ksz_get_stats64(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL_GPL(ksz_get_stats64);
+void ksz_get_strings(struct dsa_switch *ds, int port,
+ u32 stringset, uint8_t *buf)
+{
+ struct ksz_device *dev = ds->priv;
+ int i;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (i = 0; i < dev->info->mib_cnt; i++) {
+ memcpy(buf + i * ETH_GSTRING_LEN,
+ dev->info->mib_names[i].string, ETH_GSTRING_LEN);
+ }
+}
+EXPORT_SYMBOL_GPL(ksz_get_strings);
+
void ksz_update_port_member(struct ksz_device *dev, int port)
{
struct ksz_port *p = &dev->ports[port];
@@ -181,17 +597,17 @@ static void port_r_cnt(struct ksz_device *dev, int port)
u64 *dropped;
/* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */
- while (mib->cnt_ptr < dev->reg_mib_cnt) {
+ while (mib->cnt_ptr < dev->info->reg_mib_cnt) {
dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr,
&mib->counters[mib->cnt_ptr]);
++mib->cnt_ptr;
}
/* last one in storage */
- dropped = &mib->counters[dev->mib_cnt];
+ dropped = &mib->counters[dev->info->mib_cnt];
/* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
- while (mib->cnt_ptr < dev->mib_cnt) {
+ while (mib->cnt_ptr < dev->info->mib_cnt) {
dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
dropped, &mib->counters[mib->cnt_ptr]);
++mib->cnt_ptr;
@@ -207,7 +623,7 @@ static void ksz_mib_read_work(struct work_struct *work)
struct ksz_port *p;
int i;
- for (i = 0; i < dev->port_cnt; i++) {
+ for (i = 0; i < dev->info->port_cnt; i++) {
if (dsa_is_unused_port(dev->ds, i))
continue;
@@ -222,7 +638,7 @@ static void ksz_mib_read_work(struct work_struct *work)
const struct dsa_port *dp = dsa_to_port(dev->ds, i);
if (!netif_carrier_ok(dp->slave))
- mib->cnt_ptr = dev->reg_mib_cnt;
+ mib->cnt_ptr = dev->info->reg_mib_cnt;
}
port_r_cnt(dev, i);
p->read = false;
@@ -242,8 +658,14 @@ void ksz_init_mib_timer(struct ksz_device *dev)
INIT_DELAYED_WORK(&dev->mib_read, ksz_mib_read_work);
- for (i = 0; i < dev->port_cnt; i++)
+ for (i = 0; i < dev->info->port_cnt; i++) {
+ struct ksz_port_mib *mib = &dev->ports[i].mib;
+
dev->dev_ops->port_init_cnt(dev, i);
+
+ mib->cnt_ptr = 0;
+ memset(mib->counters, 0, dev->info->mib_cnt * sizeof(u64));
+ }
}
EXPORT_SYMBOL_GPL(ksz_init_mib_timer);
@@ -289,7 +711,7 @@ int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
if (sset != ETH_SS_STATS)
return 0;
- return dev->mib_cnt;
+ return dev->info->mib_cnt;
}
EXPORT_SYMBOL_GPL(ksz_sset_count);
@@ -304,9 +726,9 @@ void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf)
/* Only read dropped counters if no link. */
if (!netif_carrier_ok(dp->slave))
- mib->cnt_ptr = dev->reg_mib_cnt;
+ mib->cnt_ptr = dev->info->reg_mib_cnt;
port_r_cnt(dev, port);
- memcpy(buf, mib->counters, dev->mib_cnt * sizeof(u64));
+ memcpy(buf, mib->counters, dev->info->mib_cnt * sizeof(u64));
mutex_unlock(&mib->cnt_mutex);
}
EXPORT_SYMBOL_GPL(ksz_get_ethtool_stats);
@@ -382,7 +804,7 @@ int ksz_port_mdb_add(struct dsa_switch *ds, int port,
int empty = 0;
alu.port_forward = 0;
- for (index = 0; index < dev->num_statics; index++) {
+ for (index = 0; index < dev->info->num_statics; index++) {
if (!dev->dev_ops->r_sta_mac_table(dev, index, &alu)) {
/* Found one already in static MAC table. */
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) &&
@@ -395,11 +817,11 @@ int ksz_port_mdb_add(struct dsa_switch *ds, int port,
}
/* no available entry */
- if (index == dev->num_statics && !empty)
+ if (index == dev->info->num_statics && !empty)
return -ENOSPC;
/* add entry */
- if (index == dev->num_statics) {
+ if (index == dev->info->num_statics) {
index = empty - 1;
memset(&alu, 0, sizeof(alu));
memcpy(alu.mac, mdb->addr, ETH_ALEN);
@@ -426,7 +848,7 @@ int ksz_port_mdb_del(struct dsa_switch *ds, int port,
struct alu_struct alu;
int index;
- for (index = 0; index < dev->num_statics; index++) {
+ for (index = 0; index < dev->info->num_statics; index++) {
if (!dev->dev_ops->r_sta_mac_table(dev, index, &alu)) {
/* Found one already in static MAC table. */
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) &&
@@ -436,7 +858,7 @@ int ksz_port_mdb_del(struct dsa_switch *ds, int port,
}
/* no available entry */
- if (index == dev->num_statics)
+ if (index == dev->info->num_statics)
goto exit;
/* clear port */
@@ -537,10 +959,12 @@ EXPORT_SYMBOL(ksz_switch_alloc);
int ksz_switch_register(struct ksz_device *dev,
const struct ksz_dev_ops *ops)
{
+ const struct ksz_chip_data *info;
struct device_node *port, *ports;
phy_interface_t interface;
unsigned int port_num;
int ret;
+ int i;
if (dev->pdata)
dev->chip_id = dev->pdata->chip_id;
@@ -567,14 +991,45 @@ int ksz_switch_register(struct ksz_device *dev,
if (dev->dev_ops->detect(dev))
return -EINVAL;
+ info = ksz_lookup_info(dev->chip_id);
+ if (!info)
+ return -ENODEV;
+
+ /* Update the compatible info with the probed one */
+ dev->info = info;
+
+ ret = ksz_check_device_id(dev);
+ if (ret)
+ return ret;
+
ret = dev->dev_ops->init(dev);
if (ret)
return ret;
+ dev->ports = devm_kzalloc(dev->dev,
+ dev->info->port_cnt * sizeof(struct ksz_port),
+ GFP_KERNEL);
+ if (!dev->ports)
+ return -ENOMEM;
+
+ for (i = 0; i < dev->info->port_cnt; i++) {
+ spin_lock_init(&dev->ports[i].mib.stats64_lock);
+ mutex_init(&dev->ports[i].mib.cnt_mutex);
+ dev->ports[i].mib.counters =
+ devm_kzalloc(dev->dev,
+ sizeof(u64) * (dev->info->mib_cnt + 1),
+ GFP_KERNEL);
+ if (!dev->ports[i].mib.counters)
+ return -ENOMEM;
+ }
+
+ /* set the real number of ports */
+ dev->ds->num_ports = dev->info->port_cnt;
+
/* Host port interface will be self detected, or specifically set in
* device tree.
*/
- for (port_num = 0; port_num < dev->port_cnt; ++port_num)
+ for (port_num = 0; port_num < dev->info->port_cnt; ++port_num)
dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA;
if (dev->dev->of_node) {
ret = of_get_phy_mode(dev->dev->of_node, &interface);
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 28cda79b090f..8500eaedad67 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -14,6 +14,8 @@
#include <linux/regmap.h>
#include <net/dsa.h>
+#define KSZ_MAX_NUM_PORTS 8
+
struct vlan_table {
u32 table[3];
};
@@ -26,6 +28,30 @@ struct ksz_port_mib {
struct spinlock stats64_lock;
};
+struct ksz_mib_names {
+ int index;
+ char string[ETH_GSTRING_LEN];
+};
+
+struct ksz_chip_data {
+ u32 chip_id;
+ const char *dev_name;
+ int num_vlans;
+ int num_alus;
+ int num_statics;
+ int cpu_ports;
+ int port_cnt;
+ bool phy_errata_9477;
+ bool ksz87xx_eee_link_erratum;
+ const struct ksz_mib_names *mib_names;
+ int mib_cnt;
+ u8 reg_mib_cnt;
+ bool supports_mii[KSZ_MAX_NUM_PORTS];
+ bool supports_rmii[KSZ_MAX_NUM_PORTS];
+ bool supports_rgmii[KSZ_MAX_NUM_PORTS];
+ bool internal_phy[KSZ_MAX_NUM_PORTS];
+};
+
struct ksz_port {
bool remove_tag; /* Remove Tag flag set, for ksz8795 only */
int stp_state;
@@ -47,7 +73,7 @@ struct ksz_port {
struct ksz_device {
struct dsa_switch *ds;
struct ksz_platform_data *pdata;
- const char *name;
+ const struct ksz_chip_data *info;
struct mutex dev_mutex; /* device access */
struct mutex regmap_mutex; /* regmap access */
@@ -64,20 +90,9 @@ struct ksz_device {
/* chip specific data */
u32 chip_id;
- int num_vlans;
- int num_alus;
- int num_statics;
int cpu_port; /* port connected to CPU */
- int cpu_ports; /* port bitmap can be cpu port */
int phy_port_cnt;
- int port_cnt;
- u8 reg_mib_cnt;
- int mib_cnt;
- const struct mib_names *mib_names;
phy_interface_t compat_interface;
- u32 regs_size;
- bool phy_errata_9477;
- bool ksz87xx_eee_link_erratum;
bool synclko_125;
bool synclko_disable;
@@ -89,11 +104,42 @@ struct ksz_device {
u16 mirror_rx;
u16 mirror_tx;
u32 features; /* chip specific features */
- u32 overrides; /* chip functions set by user */
- u16 host_mask;
u16 port_mask;
};
+/* List of supported models */
+enum ksz_model {
+ KSZ8795,
+ KSZ8794,
+ KSZ8765,
+ KSZ8830,
+ KSZ9477,
+ KSZ9897,
+ KSZ9893,
+ KSZ9567,
+ LAN9370,
+ LAN9371,
+ LAN9372,
+ LAN9373,
+ LAN9374,
+};
+
+enum ksz_chip_id {
+ KSZ8795_CHIP_ID = 0x8795,
+ KSZ8794_CHIP_ID = 0x8794,
+ KSZ8765_CHIP_ID = 0x8765,
+ KSZ8830_CHIP_ID = 0x8830,
+ KSZ9477_CHIP_ID = 0x00947700,
+ KSZ9897_CHIP_ID = 0x00989700,
+ KSZ9893_CHIP_ID = 0x00989300,
+ KSZ9567_CHIP_ID = 0x00956700,
+ LAN9370_CHIP_ID = 0x00937000,
+ LAN9371_CHIP_ID = 0x00937100,
+ LAN9372_CHIP_ID = 0x00937200,
+ LAN9373_CHIP_ID = 0x00937300,
+ LAN9374_CHIP_ID = 0x00937400,
+};
+
struct alu_struct {
/* entry 1 */
u8 is_static:1;
@@ -154,6 +200,9 @@ void ksz_init_mib_timer(struct ksz_device *dev);
void ksz_r_mib_stats64(struct ksz_device *dev, int port);
void ksz_get_stats64(struct dsa_switch *ds, int port,
struct rtnl_link_stats64 *s);
+void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config);
+extern const struct ksz_chip_data ksz_switch_chips[];
/* Common DSA access functions */
@@ -180,6 +229,8 @@ int ksz_port_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db);
int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
+void ksz_get_strings(struct dsa_switch *ds, int port,
+ u32 stringset, uint8_t *buf);
/* Common register access functions */
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 1a3406b9e64c..25f88022b9e4 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -1653,29 +1653,37 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
if (phy > RTL8366RB_PHY_NO_MAX)
return -EINVAL;
- ret = regmap_write(priv->map, RTL8366RB_PHY_ACCESS_CTRL_REG,
+ mutex_lock(&priv->map_lock);
+
+ ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
RTL8366RB_PHY_CTRL_READ);
if (ret)
- return ret;
+ goto out;
reg = 0x8000 | (1 << (phy + RTL8366RB_PHY_NO_OFFSET)) | regnum;
- ret = regmap_write(priv->map, reg, 0);
+ ret = regmap_write(priv->map_nolock, reg, 0);
if (ret) {
dev_err(priv->dev,
"failed to write PHY%d reg %04x @ %04x, ret %d\n",
phy, regnum, reg, ret);
- return ret;
+ goto out;
}
- ret = regmap_read(priv->map, RTL8366RB_PHY_ACCESS_DATA_REG, &val);
+ ret = regmap_read(priv->map_nolock, RTL8366RB_PHY_ACCESS_DATA_REG,
+ &val);
if (ret)
- return ret;
+ goto out;
+
+ ret = val;
dev_dbg(priv->dev, "read PHY%d register 0x%04x @ %08x, val <- %04x\n",
phy, regnum, reg, val);
- return val;
+out:
+ mutex_unlock(&priv->map_lock);
+
+ return ret;
}
static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
@@ -1687,21 +1695,26 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
if (phy > RTL8366RB_PHY_NO_MAX)
return -EINVAL;
- ret = regmap_write(priv->map, RTL8366RB_PHY_ACCESS_CTRL_REG,
+ mutex_lock(&priv->map_lock);
+
+ ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
RTL8366RB_PHY_CTRL_WRITE);
if (ret)
- return ret;
+ goto out;
reg = 0x8000 | (1 << (phy + RTL8366RB_PHY_NO_OFFSET)) | regnum;
dev_dbg(priv->dev, "write PHY%d register 0x%04x @ %04x, val -> %04x\n",
phy, regnum, reg, val);
- ret = regmap_write(priv->map, reg, val);
+ ret = regmap_write(priv->map_nolock, reg, val);
if (ret)
- return ret;
+ goto out;
- return 0;
+out:
+ mutex_unlock(&priv->map_lock);
+
+ return ret;
}
static int rtl8366rb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 607a2c90513b..d9547552ceef 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -151,7 +151,8 @@
#define XGBE_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1))
/* Descriptors required for maximum contiguous TSO/GSO packet */
-#define XGBE_TX_MAX_SPLIT ((GSO_MAX_SIZE / XGBE_TX_MAX_BUF_SIZE) + 1)
+#define XGBE_TX_MAX_SPLIT \
+ ((GSO_LEGACY_MAX_SIZE / XGBE_TX_MAX_BUF_SIZE) + 1)
/* Maximum possible descriptors needed for an SKB:
* - Maximum number of SKB frags
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index a4ce96bb3903..3272aca496dc 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -2585,8 +2585,10 @@ static int bcm_sysport_probe(struct platform_device *pdev)
device_set_wakeup_capable(&pdev->dev, 1);
priv->wol_clk = devm_clk_get_optional(&pdev->dev, "sw_sysportwol");
- if (IS_ERR(priv->wol_clk))
- return PTR_ERR(priv->wol_clk);
+ if (IS_ERR(priv->wol_clk)) {
+ ret = PTR_ERR(priv->wol_clk);
+ goto err_deregister_fixed_link;
+ }
/* Set the needed headroom once and for all */
BUILD_BUG_ON(sizeof(struct bcm_tsb) != 8);
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index e993616308f8..d6cdb97bfb38 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1213,7 +1213,6 @@ static void gem_rx_refill(struct macb_queue *queue)
/* Make hw descriptor updates visible to CPU */
rmb();
- queue->rx_prepared_head++;
desc = macb_rx_desc(queue, entry);
if (!queue->rx_skbuff[entry]) {
@@ -1252,6 +1251,7 @@ static void gem_rx_refill(struct macb_queue *queue)
dma_wmb();
desc->addr &= ~MACB_BIT(RX_USED);
}
+ queue->rx_prepared_head++;
}
/* Make descriptor updates visible to hardware */
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index a04aa206fddc..768ea426d49f 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -2024,9 +2024,6 @@ static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
u8 mode;
struct xcast_addr_list *mc;
- if (!vf_work)
- return;
-
/* Save message data locally to prevent them from
* being overwritten by next ndo_set_rx_mode call().
*/
diff --git a/drivers/net/ethernet/dec/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c
index ba0a69b363f8..67a67cb78dbb 100644
--- a/drivers/net/ethernet/dec/tulip/eeprom.c
+++ b/drivers/net/ethernet/dec/tulip/eeprom.c
@@ -117,8 +117,8 @@ static void tulip_build_fake_mediatable(struct tulip_private *tp)
0x00, 0x06 /* ttm bit map */
};
- tp->mtable = kmalloc(sizeof(struct mediatable) +
- sizeof(struct medialeaf), GFP_KERNEL);
+ tp->mtable = devm_kmalloc(&tp->pdev->pdev, sizeof(struct mediatable) +
+ sizeof(struct medialeaf), GFP_KERNEL);
if (tp->mtable == NULL)
return; /* Horrible, impossible failure. */
@@ -224,7 +224,8 @@ subsequent_board:
return;
}
- mtable = kmalloc(struct_size(mtable, mleaf, count), GFP_KERNEL);
+ mtable = devm_kmalloc(&tp->pdev->dev, struct_size(mtable, mleaf, count),
+ GFP_KERNEL);
if (mtable == NULL)
return; /* Horrible, impossible failure. */
last_mediatable = tp->mtable = mtable;
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index 825e81f5fd22..b8e46c4849ef 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -1389,7 +1389,7 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
* And back to business
*/
- i = pci_enable_device(pdev);
+ i = pcim_enable_device(pdev);
if (i) {
pr_err("Cannot enable tulip board #%d, aborting\n", board_idx);
return i;
@@ -1398,11 +1398,9 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
irq = pdev->irq;
/* alloc_etherdev ensures aligned and zeroed private structures */
- dev = alloc_etherdev (sizeof (*tp));
- if (!dev) {
- pci_disable_device(pdev);
+ dev = devm_alloc_etherdev(&pdev->dev, sizeof(*tp));
+ if (!dev)
return -ENOMEM;
- }
SET_NETDEV_DEV(dev, &pdev->dev);
if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) {
@@ -1410,18 +1408,18 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_name(pdev),
(unsigned long long)pci_resource_len (pdev, 0),
(unsigned long long)pci_resource_start (pdev, 0));
- goto err_out_free_netdev;
+ return -ENODEV;
}
/* grab all resources from both PIO and MMIO regions, as we
* don't want anyone else messing around with our hardware */
- if (pci_request_regions (pdev, DRV_NAME))
- goto err_out_free_netdev;
+ if (pci_request_regions(pdev, DRV_NAME))
+ return -ENODEV;
- ioaddr = pci_iomap(pdev, TULIP_BAR, tulip_tbl[chip_idx].io_size);
+ ioaddr = pcim_iomap(pdev, TULIP_BAR, tulip_tbl[chip_idx].io_size);
if (!ioaddr)
- goto err_out_free_res;
+ return -ENODEV;
/*
* initialize private data structure 'tp'
@@ -1430,12 +1428,12 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp = netdev_priv(dev);
tp->dev = dev;
- tp->rx_ring = dma_alloc_coherent(&pdev->dev,
- sizeof(struct tulip_rx_desc) * RX_RING_SIZE +
- sizeof(struct tulip_tx_desc) * TX_RING_SIZE,
- &tp->rx_ring_dma, GFP_KERNEL);
+ tp->rx_ring = dmam_alloc_coherent(&pdev->dev,
+ sizeof(struct tulip_rx_desc) * RX_RING_SIZE +
+ sizeof(struct tulip_tx_desc) * TX_RING_SIZE,
+ &tp->rx_ring_dma, GFP_KERNEL);
if (!tp->rx_ring)
- goto err_out_mtable;
+ return -ENODEV;
tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE);
tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE;
@@ -1695,8 +1693,9 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#endif
dev->ethtool_ops = &ops;
- if (register_netdev(dev))
- goto err_out_free_ring;
+ i = register_netdev(dev);
+ if (i)
+ return i;
pci_set_drvdata(pdev, dev);
@@ -1771,24 +1770,6 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tulip_set_power_state (tp, 0, 1);
return 0;
-
-err_out_free_ring:
- dma_free_coherent(&pdev->dev,
- sizeof(struct tulip_rx_desc) * RX_RING_SIZE +
- sizeof(struct tulip_tx_desc) * TX_RING_SIZE,
- tp->rx_ring, tp->rx_ring_dma);
-
-err_out_mtable:
- kfree (tp->mtable);
- pci_iounmap(pdev, ioaddr);
-
-err_out_free_res:
- pci_release_regions (pdev);
-
-err_out_free_netdev:
- free_netdev (dev);
- pci_disable_device(pdev);
- return -ENODEV;
}
@@ -1888,24 +1869,11 @@ static int __maybe_unused tulip_resume(struct device *dev_d)
static void tulip_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata (pdev);
- struct tulip_private *tp;
if (!dev)
return;
- tp = netdev_priv(dev);
unregister_netdev(dev);
- dma_free_coherent(&pdev->dev,
- sizeof(struct tulip_rx_desc) * RX_RING_SIZE +
- sizeof(struct tulip_tx_desc) * TX_RING_SIZE,
- tp->rx_ring, tp->rx_ring_dma);
- kfree (tp->mtable);
- pci_iounmap(pdev, tp->base_addr);
- free_netdev (dev);
- pci_release_regions (pdev);
- pci_disable_device(pdev);
-
- /* pci_power_off (pdev, -1); */
}
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index caf48023f8ea..5231818943c6 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1928,6 +1928,11 @@ static int ftgmac100_probe(struct platform_device *pdev)
/* AST2400 doesn't have working HW checksum generation */
if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac")))
netdev->hw_features &= ~NETIF_F_HW_CSUM;
+
+ /* AST2600 tx checksum with NCSI is broken */
+ if (priv->use_ncsi && of_device_is_compatible(np, "aspeed,ast2600-mac"))
+ netdev->hw_features &= ~NETIF_F_HW_CSUM;
+
if (np && of_get_property(np, "no-hw-checksum", NULL))
netdev->hw_features &= ~(NETIF_F_HW_CSUM | NETIF_F_RXCSUM);
netdev->features |= netdev->hw_features;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 6e52f3ad182f..3cb298f1d69c 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3076,7 +3076,7 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
rxq = fep->rx_queue[queue];
bdp = rxq->bd.base;
for (i = 0; i < rxq->bd.ring_size; i++) {
- skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
+ skb = __netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE, GFP_KERNEL);
if (!skb)
goto err_alloc;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
index ebc77771f5da..4aa1f433ed24 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
@@ -643,6 +643,7 @@ int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
err = alloc_msg_buf(pf_to_mgmt);
if (err) {
dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
+ destroy_workqueue(pf_to_mgmt->workq);
hinic_health_reporters_destroy(hwdev->devlink_dev);
return err;
}
@@ -650,6 +651,7 @@ int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
if (err) {
dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
+ destroy_workqueue(pf_to_mgmt->workq);
hinic_health_reporters_destroy(hwdev->devlink_dev);
return err;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 6d19c58ccacd..454e01ae09b9 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -3043,8 +3043,8 @@ ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi,
ice_for_each_q_vector(vsi, i) {
struct ice_q_vector *q_vector = vsi->q_vectors[i];
- coalesce[i].itr_tx = q_vector->tx.itr_setting;
- coalesce[i].itr_rx = q_vector->rx.itr_setting;
+ coalesce[i].itr_tx = q_vector->tx.itr_settings;
+ coalesce[i].itr_rx = q_vector->rx.itr_settings;
coalesce[i].intrl = q_vector->intrl;
if (i < vsi->num_txq)
@@ -3100,21 +3100,21 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
*/
if (i < vsi->alloc_rxq && coalesce[i].rx_valid) {
rc = &vsi->q_vectors[i]->rx;
- rc->itr_setting = coalesce[i].itr_rx;
+ rc->itr_settings = coalesce[i].itr_rx;
ice_write_itr(rc, rc->itr_setting);
} else if (i < vsi->alloc_rxq) {
rc = &vsi->q_vectors[i]->rx;
- rc->itr_setting = coalesce[0].itr_rx;
+ rc->itr_settings = coalesce[0].itr_rx;
ice_write_itr(rc, rc->itr_setting);
}
if (i < vsi->alloc_txq && coalesce[i].tx_valid) {
rc = &vsi->q_vectors[i]->tx;
- rc->itr_setting = coalesce[i].itr_tx;
+ rc->itr_settings = coalesce[i].itr_tx;
ice_write_itr(rc, rc->itr_setting);
} else if (i < vsi->alloc_txq) {
rc = &vsi->q_vectors[i]->tx;
- rc->itr_setting = coalesce[0].itr_tx;
+ rc->itr_settings = coalesce[0].itr_tx;
ice_write_itr(rc, rc->itr_setting);
}
@@ -3128,12 +3128,12 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
for (; i < vsi->num_q_vectors; i++) {
/* transmit */
rc = &vsi->q_vectors[i]->tx;
- rc->itr_setting = coalesce[0].itr_tx;
+ rc->itr_settings = coalesce[0].itr_tx;
ice_write_itr(rc, rc->itr_setting);
/* receive */
rc = &vsi->q_vectors[i]->rx;
- rc->itr_setting = coalesce[0].itr_rx;
+ rc->itr_settings = coalesce[0].itr_rx;
ice_write_itr(rc, rc->itr_setting);
vsi->q_vectors[i]->intrl = coalesce[0].intrl;
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 4a5d4d971161..e1cae253412c 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -6189,9 +6189,10 @@ static int ice_up_complete(struct ice_vsi *vsi)
ice_ptp_link_change(pf, pf->hw.pf_id, true);
}
- /* clear this now, and the first stats read will be used as baseline */
- vsi->stat_offsets_loaded = false;
-
+ /* Perform an initial read of the statistics registers now to
+ * set the baseline so counters are ready when interface is up
+ */
+ ice_update_eth_stats(vsi);
ice_service_task_schedule(pf);
return 0;
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index da025c204577..662947c882e8 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -500,12 +500,19 @@ ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts)
* 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 void ice_ptp_update_cached_phctime(struct ice_pf *pf)
+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);
@@ -528,6 +535,9 @@ static void ice_ptp_update_cached_phctime(struct ice_pf *pf)
WRITE_ONCE(vsi->rx_rings[j]->cached_phctime, systime);
}
}
+ clear_bit(ICE_CFG_BUSY, pf->state);
+
+ return 0;
}
/**
@@ -2330,17 +2340,18 @@ static void ice_ptp_periodic_work(struct kthread_work *work)
{
struct ice_ptp *ptp = container_of(work, struct ice_ptp, work.work);
struct ice_pf *pf = container_of(ptp, struct ice_pf, ptp);
+ int err;
if (!test_bit(ICE_FLAG_PTP, pf->flags))
return;
- ice_ptp_update_cached_phctime(pf);
+ err = ice_ptp_update_cached_phctime(pf);
ice_ptp_tx_tstamp_cleanup(&pf->hw, &pf->ptp.port.tx);
- /* Run twice a second */
+ /* Run twice a second or reschedule if phc update failed */
kthread_queue_delayed_work(ptp->kworker, &ptp->work,
- msecs_to_jiffies(500));
+ msecs_to_jiffies(err ? 10 : 500));
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h
index f5a906c03669..ca902af54bb4 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.h
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.h
@@ -385,9 +385,14 @@ struct ice_ring_container {
/* this matches the maximum number of ITR bits, but in usec
* values, so it is shifted left one bit (bit zero is ignored)
*/
- u16 itr_setting:13;
- u16 itr_reserved:2;
- u16 itr_mode:1;
+ union {
+ struct {
+ u16 itr_setting:13;
+ u16 itr_reserved:2;
+ u16 itr_mode:1;
+ };
+ u16 itr_settings;
+ };
enum ice_container_type type;
};
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 34b33b21e0dc..68be2976f539 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -5505,7 +5505,8 @@ static void igb_watchdog_task(struct work_struct *work)
break;
}
- if (adapter->link_speed != SPEED_1000)
+ if (adapter->link_speed != SPEED_1000 ||
+ !hw->phy.ops.read_reg)
goto no_wait;
/* wait for Remote receiver status OK */
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index e020c81f3455..97f080c66dd4 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -202,7 +202,7 @@ static int octep_request_irqs(struct octep_device *oct)
struct msix_entry *msix_entry;
char **non_ioq_msix_names;
int num_non_ioq_msix;
- int ret, i;
+ int ret, i, j;
num_non_ioq_msix = CFG_GET_NON_IOQ_MSIX(oct->conf);
non_ioq_msix_names = CFG_GET_NON_IOQ_MSIX_NAMES(oct->conf);
@@ -233,23 +233,23 @@ static int octep_request_irqs(struct octep_device *oct)
}
/* Request IRQs for Tx/Rx queues */
- for (i = 0; i < oct->num_oqs; i++) {
- ioq_vector = oct->ioq_vector[i];
- msix_entry = &oct->msix_entries[i + num_non_ioq_msix];
+ for (j = 0; j < oct->num_oqs; j++) {
+ ioq_vector = oct->ioq_vector[j];
+ msix_entry = &oct->msix_entries[j + num_non_ioq_msix];
snprintf(ioq_vector->name, sizeof(ioq_vector->name),
- "%s-q%d", netdev->name, i);
+ "%s-q%d", netdev->name, j);
ret = request_irq(msix_entry->vector,
octep_ioq_intr_handler, 0,
ioq_vector->name, ioq_vector);
if (ret) {
netdev_err(netdev,
"request_irq failed for Q-%d; err=%d",
- i, ret);
+ j, ret);
goto ioq_irq_err;
}
- cpumask_set_cpu(i % num_online_cpus(),
+ cpumask_set_cpu(j % num_online_cpus(),
&ioq_vector->affinity_mask);
irq_set_affinity_hint(msix_entry->vector,
&ioq_vector->affinity_mask);
@@ -257,16 +257,21 @@ static int octep_request_irqs(struct octep_device *oct)
return 0;
ioq_irq_err:
- while (i > num_non_ioq_msix) {
- --i;
- irq_set_affinity_hint(oct->msix_entries[i].vector, NULL);
- free_irq(oct->msix_entries[i].vector, oct->ioq_vector[i]);
+ while (j) {
+ --j;
+ ioq_vector = oct->ioq_vector[j];
+ msix_entry = &oct->msix_entries[j + num_non_ioq_msix];
+
+ irq_set_affinity_hint(msix_entry->vector, NULL);
+ free_irq(msix_entry->vector, ioq_vector);
}
non_ioq_irq_err:
while (i) {
--i;
free_irq(oct->msix_entries[i].vector, oct);
}
+ kfree(oct->non_ioq_irq_names);
+ oct->non_ioq_irq_names = NULL;
alloc_err:
return -1;
}
@@ -980,8 +985,7 @@ static void octep_device_cleanup(struct octep_device *oct)
dev_info(&oct->pdev->dev, "Cleaning up Octeon Device ...\n");
for (i = 0; i < OCTEP_MAX_VF; i++) {
- if (oct->mbox[i])
- vfree(oct->mbox[i]);
+ vfree(oct->mbox[i]);
oct->mbox[i] = NULL;
}
@@ -1149,6 +1153,7 @@ static int __init octep_init_module(void)
if (ret < 0) {
pr_err("%s: Failed to register PCI driver; err=%d\n",
OCTEP_DRV_NAME, ret);
+ destroy_workqueue(octep_wq);
return ret;
}
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
index 945947ec7723..d9ae0937d17a 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
@@ -230,8 +230,7 @@ static int octep_free_oq(struct octep_oq *oq)
octep_oq_free_ring_buffers(oq);
- if (oq->buff_info)
- vfree(oq->buff_info);
+ vfree(oq->buff_info);
if (oq->desc_ring)
dma_free_coherent(oq->dev,
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_tx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_tx.c
index 511552bc3e87..5a520d37bea0 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_tx.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_tx.c
@@ -270,8 +270,7 @@ static void octep_free_iq(struct octep_iq *iq)
desc_ring_size = OCTEP_IQ_DESC_SIZE * CFG_GET_IQ_NUM_DESC(oct->conf);
- if (iq->buff_info)
- vfree(iq->buff_info);
+ vfree(iq->buff_info);
if (iq->desc_ring)
dma_free_coherent(iq->dev, desc_ring_size,
diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig
index 639893d87055..e1036b0eb6b1 100644
--- a/drivers/net/ethernet/marvell/octeontx2/Kconfig
+++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig
@@ -33,6 +33,7 @@ config OCTEONTX2_PF
select OCTEONTX2_MBOX
select NET_DEVLINK
depends on (64BIT && COMPILE_TEST) || ARM64
+ select DIMLIB
depends on PCI
depends on PTP_1588_CLOCK_OPTIONAL
help
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index b9d7601138ca..fb8db5888d2f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -97,11 +97,6 @@ void otx2_get_dev_stats(struct otx2_nic *pfvf)
{
struct otx2_dev_stats *dev_stats = &pfvf->hw.dev_stats;
-#define OTX2_GET_RX_STATS(reg) \
- otx2_read64(pfvf, NIX_LF_RX_STATX(reg))
-#define OTX2_GET_TX_STATS(reg) \
- otx2_read64(pfvf, NIX_LF_TX_STATX(reg))
-
dev_stats->rx_bytes = OTX2_GET_RX_STATS(RX_OCTS);
dev_stats->rx_drops = OTX2_GET_RX_STATS(RX_DROP);
dev_stats->rx_bcast_frames = OTX2_GET_RX_STATS(RX_BCAST);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index c587c14ac2a3..ce2766317c0b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -18,6 +18,7 @@
#include <net/pkt_cls.h>
#include <net/devlink.h>
#include <linux/time64.h>
+#include <linux/dim.h>
#include <mbox.h>
#include <npc.h>
@@ -54,6 +55,11 @@ enum arua_mapped_qtypes {
/* Send skid of 2000 packets required for CQ size of 4K CQEs. */
#define SEND_CQ_SKID 2000
+#define OTX2_GET_RX_STATS(reg) \
+ otx2_read64(pfvf, NIX_LF_RX_STATX(reg))
+#define OTX2_GET_TX_STATS(reg) \
+ otx2_read64(pfvf, NIX_LF_TX_STATX(reg))
+
struct otx2_lmt_info {
u64 lmt_addr;
u16 lmt_id;
@@ -351,6 +357,7 @@ struct otx2_nic {
#define OTX2_FLAG_TC_MATCHALL_EGRESS_ENABLED BIT_ULL(12)
#define OTX2_FLAG_TC_MATCHALL_INGRESS_ENABLED BIT_ULL(13)
#define OTX2_FLAG_DMACFLTR_SUPPORT BIT_ULL(14)
+#define OTX2_FLAG_ADPTV_INT_COAL_ENABLED BIT_ULL(16)
u64 flags;
u64 *cq_op_addr;
@@ -408,6 +415,9 @@ struct otx2_nic {
u8 pfc_en;
u8 *queue_to_pfc_map;
#endif
+
+ /* napi event count. It is needed for adaptive irq coalescing. */
+ u32 napi_events;
};
static inline bool is_otx2_lbkvf(struct pci_dev *pdev)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index fc328de5345e..bc614a4def9e 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -455,6 +455,14 @@ static int otx2_get_coalesce(struct net_device *netdev,
cmd->rx_max_coalesced_frames = hw->cq_ecount_wait;
cmd->tx_coalesce_usecs = hw->cq_time_wait;
cmd->tx_max_coalesced_frames = hw->cq_ecount_wait;
+ if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) ==
+ OTX2_FLAG_ADPTV_INT_COAL_ENABLED) {
+ cmd->use_adaptive_rx_coalesce = 1;
+ cmd->use_adaptive_tx_coalesce = 1;
+ } else {
+ cmd->use_adaptive_rx_coalesce = 0;
+ cmd->use_adaptive_tx_coalesce = 0;
+ }
return 0;
}
@@ -466,11 +474,30 @@ static int otx2_set_coalesce(struct net_device *netdev,
{
struct otx2_nic *pfvf = netdev_priv(netdev);
struct otx2_hw *hw = &pfvf->hw;
+ u8 priv_coalesce_status;
int qidx;
if (!ec->rx_max_coalesced_frames || !ec->tx_max_coalesced_frames)
return 0;
+ if (ec->use_adaptive_rx_coalesce != ec->use_adaptive_tx_coalesce) {
+ netdev_err(netdev,
+ "adaptive-rx should be same as adaptive-tx");
+ return -EINVAL;
+ }
+
+ /* Check and update coalesce status */
+ if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) ==
+ OTX2_FLAG_ADPTV_INT_COAL_ENABLED) {
+ priv_coalesce_status = 1;
+ if (!ec->use_adaptive_rx_coalesce)
+ pfvf->flags &= ~OTX2_FLAG_ADPTV_INT_COAL_ENABLED;
+ } else {
+ priv_coalesce_status = 0;
+ if (ec->use_adaptive_rx_coalesce)
+ pfvf->flags |= OTX2_FLAG_ADPTV_INT_COAL_ENABLED;
+ }
+
/* 'cq_time_wait' is 8bit and is in multiple of 100ns,
* so clamp the user given value to the range of 1 to 25usec.
*/
@@ -494,9 +521,9 @@ static int otx2_set_coalesce(struct net_device *netdev,
* so clamp the user given value to the range of 1 to 64k.
*/
ec->rx_max_coalesced_frames = clamp_t(u32, ec->rx_max_coalesced_frames,
- 1, U16_MAX);
+ 1, NAPI_POLL_WEIGHT);
ec->tx_max_coalesced_frames = clamp_t(u32, ec->tx_max_coalesced_frames,
- 1, U16_MAX);
+ 1, NAPI_POLL_WEIGHT);
/* Rx and Tx are mapped to same CQ, check which one
* is changed, if both then choose the min.
@@ -509,6 +536,17 @@ static int otx2_set_coalesce(struct net_device *netdev,
hw->cq_ecount_wait = min_t(u16, ec->rx_max_coalesced_frames,
ec->tx_max_coalesced_frames);
+ /* Reset 'cq_time_wait' and 'cq_ecount_wait' to
+ * default values if coalesce status changed from
+ * 'on' to 'off'.
+ */
+ if (priv_coalesce_status &&
+ ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) !=
+ OTX2_FLAG_ADPTV_INT_COAL_ENABLED)) {
+ hw->cq_time_wait = CQ_TIMER_THRESH_DEFAULT;
+ hw->cq_ecount_wait = CQ_CQE_THRESH_DEFAULT;
+ }
+
if (netif_running(netdev)) {
for (qidx = 0; qidx < pfvf->hw.cint_cnt; qidx++)
otx2_config_irq_coalescing(pfvf, qidx);
@@ -1230,7 +1268,8 @@ end:
static const struct ethtool_ops otx2_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
- ETHTOOL_COALESCE_MAX_FRAMES,
+ ETHTOOL_COALESCE_MAX_FRAMES |
+ ETHTOOL_COALESCE_USE_ADAPTIVE,
.supported_ring_params = ETHTOOL_RING_USE_RX_BUF_LEN |
ETHTOOL_RING_USE_CQE_SIZE,
.get_link = otx2_get_link,
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 53b2706d65a1..fe3472e04c23 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1254,6 +1254,7 @@ static irqreturn_t otx2_cq_intr_handler(int irq, void *cq_irq)
otx2_write64(pf, NIX_LF_CINTX_ENA_W1C(qidx), BIT_ULL(0));
/* Schedule NAPI */
+ pf->napi_events++;
napi_schedule_irqoff(&cq_poll->napi);
return IRQ_HANDLED;
@@ -1267,6 +1268,7 @@ static void otx2_disable_napi(struct otx2_nic *pf)
for (qidx = 0; qidx < pf->hw.cint_cnt; qidx++) {
cq_poll = &qset->napi[qidx];
+ cancel_work_sync(&cq_poll->dim.work);
napi_disable(&cq_poll->napi);
netif_napi_del(&cq_poll->napi);
}
@@ -1546,6 +1548,24 @@ static void otx2_do_set_rx_mode(struct otx2_nic *pf)
mutex_unlock(&pf->mbox.lock);
}
+static void otx2_dim_work(struct work_struct *w)
+{
+ struct dim_cq_moder cur_moder;
+ struct otx2_cq_poll *cq_poll;
+ struct otx2_nic *pfvf;
+ struct dim *dim;
+
+ dim = container_of(w, struct dim, work);
+ cur_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
+ cq_poll = container_of(dim, struct otx2_cq_poll, dim);
+ pfvf = (struct otx2_nic *)cq_poll->dev;
+ pfvf->hw.cq_time_wait = (cur_moder.usec > CQ_TIMER_THRESH_MAX) ?
+ CQ_TIMER_THRESH_MAX : cur_moder.usec;
+ pfvf->hw.cq_ecount_wait = (cur_moder.pkts > NAPI_POLL_WEIGHT) ?
+ NAPI_POLL_WEIGHT : cur_moder.pkts;
+ dim->state = DIM_START_MEASURE;
+}
+
int otx2_open(struct net_device *netdev)
{
struct otx2_nic *pf = netdev_priv(netdev);
@@ -1612,6 +1632,8 @@ int otx2_open(struct net_device *netdev)
cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;
cq_poll->dev = (void *)pf;
+ cq_poll->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE;
+ INIT_WORK(&cq_poll->dim.work, otx2_dim_work);
netif_napi_add(netdev, &cq_poll->napi,
otx2_napi_handler, NAPI_POLL_WEIGHT);
napi_enable(&cq_poll->napi);
@@ -1718,7 +1740,6 @@ err_free_cints:
vec = pci_irq_vector(pf->pdev,
pf->hw.nix_msixoff + NIX_LF_QINT_VEC_START);
otx2_write64(pf, NIX_LF_QINTX_ENA_W1C(0), BIT_ULL(0));
- synchronize_irq(vec);
free_irq(vec, pf);
err_disable_napi:
otx2_disable_napi(pf);
@@ -1762,7 +1783,6 @@ int otx2_stop(struct net_device *netdev)
vec = pci_irq_vector(pf->pdev,
pf->hw.nix_msixoff + NIX_LF_QINT_VEC_START);
otx2_write64(pf, NIX_LF_QINTX_ENA_W1C(0), BIT_ULL(0));
- synchronize_irq(vec);
free_irq(vec, pf);
/* Cleanup CQ NAPI and IRQ */
@@ -1796,8 +1816,7 @@ int otx2_stop(struct net_device *netdev)
kfree(qset->rq);
kfree(qset->napi);
/* Do not clear RQ/SQ ringsize settings */
- memset((void *)qset + offsetof(struct otx2_qset, sqe_cnt), 0,
- sizeof(*qset) - offsetof(struct otx2_qset, sqe_cnt));
+ memset_startat(qset, 0, sqe_cnt);
return 0;
}
EXPORT_SYMBOL(otx2_stop);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index c26de15b2ac3..3baeafc40807 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -484,6 +484,18 @@ process_cqe:
return 0;
}
+static void otx2_adjust_adaptive_coalese(struct otx2_nic *pfvf, struct otx2_cq_poll *cq_poll)
+{
+ struct dim_sample dim_sample;
+ u64 rx_frames, rx_bytes;
+
+ rx_frames = OTX2_GET_RX_STATS(RX_BCAST) + OTX2_GET_RX_STATS(RX_MCAST) +
+ OTX2_GET_RX_STATS(RX_UCAST);
+ rx_bytes = OTX2_GET_RX_STATS(RX_OCTS);
+ dim_update_sample(pfvf->napi_events, rx_frames, rx_bytes, &dim_sample);
+ net_dim(&cq_poll->dim, dim_sample);
+}
+
int otx2_napi_handler(struct napi_struct *napi, int budget)
{
struct otx2_cq_queue *rx_cq = NULL;
@@ -521,6 +533,17 @@ int otx2_napi_handler(struct napi_struct *napi, int budget)
if (pfvf->flags & OTX2_FLAG_INTF_DOWN)
return workdone;
+ /* Check for adaptive interrupt coalesce */
+ if (workdone != 0 &&
+ ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) ==
+ OTX2_FLAG_ADPTV_INT_COAL_ENABLED)) {
+ /* Adjust irq coalese using net_dim */
+ otx2_adjust_adaptive_coalese(pfvf, cq_poll);
+ /* Update irq coalescing */
+ for (i = 0; i < pfvf->hw.cint_cnt; i++)
+ otx2_config_irq_coalescing(pfvf, i);
+ }
+
/* Re-enable interrupts */
otx2_write64(pfvf, NIX_LF_CINTX_ENA_W1S(cq_poll->cint_idx),
BIT_ULL(0));
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
index f1a04cf9210c..c88e8a436029 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
@@ -109,6 +109,7 @@ struct otx2_cq_poll {
#define CINT_INVALID_CQ 255
u8 cint_idx;
u8 cq_ids[CQS_PER_CINT];
+ struct dim dim;
struct napi_struct napi;
};
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 31c5da5d6b72..16f131445d8b 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -263,14 +263,33 @@ static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth,
mtk_w32(eth, val, TRGMII_TCK_CTRL);
}
+static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config,
+ phy_interface_t interface)
+{
+ struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ phylink_config);
+ struct mtk_eth *eth = mac->hw;
+ unsigned int sid;
+
+ if (interface == PHY_INTERFACE_MODE_SGMII ||
+ phy_interface_mode_is_8023z(interface)) {
+ sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
+ 0 : mac->id;
+
+ return mtk_sgmii_select_pcs(eth->sgmii, sid);
+ }
+
+ return NULL;
+}
+
static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
struct mtk_eth *eth = mac->hw;
- u32 mcr_cur, mcr_new, sid, i;
int val, ge_mode, err = 0;
+ u32 i;
/* MT76x8 has no hardware settings between for the MAC */
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
@@ -327,6 +346,14 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
state->interface))
goto err_phy;
} else {
+ /* FIXME: this is incorrect. Not only does it
+ * use state->speed (which is not guaranteed
+ * to be correct) but it also makes use of it
+ * in a code path that will only be reachable
+ * when the PHY interface mode changes, not
+ * when the speed changes. Consequently, RGMII
+ * is probably broken.
+ */
mtk_gmac0_rgmii_adjust(mac->hw,
state->interface,
state->speed);
@@ -383,38 +410,14 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
SYSCFG0_SGMII_MASK,
~(u32)SYSCFG0_SGMII_MASK);
- /* Decide how GMAC and SGMIISYS be mapped */
- sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
- 0 : mac->id;
-
- /* Setup SGMIISYS with the determined property */
- if (state->interface != PHY_INTERFACE_MODE_SGMII)
- err = mtk_sgmii_setup_mode_force(eth->sgmii, sid,
- state);
- else if (phylink_autoneg_inband(mode))
- err = mtk_sgmii_setup_mode_an(eth->sgmii, sid);
-
- if (err)
- goto init_err;
-
- regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
- SYSCFG0_SGMII_MASK, val);
+ /* Save the syscfg0 value for mac_finish */
+ mac->syscfg0 = val;
} else if (phylink_autoneg_inband(mode)) {
dev_err(eth->dev,
"In-band mode not supported in non SGMII mode!\n");
return;
}
- /* Setup gmac */
- mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
- mcr_new = mcr_cur;
- mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
- MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
-
- /* Only update control register when needed! */
- if (mcr_new != mcr_cur)
- mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
-
return;
err_phy:
@@ -427,6 +430,33 @@ init_err:
mac->id, phy_modes(state->interface), err);
}
+static int mtk_mac_finish(struct phylink_config *config, unsigned int mode,
+ phy_interface_t interface)
+{
+ struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ phylink_config);
+ struct mtk_eth *eth = mac->hw;
+ u32 mcr_cur, mcr_new;
+
+ /* Enable SGMII */
+ if (interface == PHY_INTERFACE_MODE_SGMII ||
+ phy_interface_mode_is_8023z(interface))
+ regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
+ SYSCFG0_SGMII_MASK, mac->syscfg0);
+
+ /* Setup gmac */
+ mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ mcr_new = mcr_cur;
+ mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
+ MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
+
+ /* Only update control register when needed! */
+ if (mcr_new != mcr_cur)
+ mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
+
+ return 0;
+}
+
static void mtk_mac_pcs_get_state(struct phylink_config *config,
struct phylink_link_state *state)
{
@@ -459,14 +489,6 @@ static void mtk_mac_pcs_get_state(struct phylink_config *config,
state->pause |= MLO_PAUSE_TX;
}
-static void mtk_mac_an_restart(struct phylink_config *config)
-{
- struct mtk_mac *mac = container_of(config, struct mtk_mac,
- phylink_config);
-
- mtk_sgmii_restart_an(mac->hw, mac->id);
-}
-
static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,
phy_interface_t interface)
{
@@ -485,8 +507,9 @@ static void mtk_mac_link_up(struct phylink_config *config,
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
- u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ u32 mcr;
+ mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 |
MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC |
MAC_MCR_FORCE_RX_FC);
@@ -518,9 +541,10 @@ static void mtk_mac_link_up(struct phylink_config *config,
static const struct phylink_mac_ops mtk_phylink_ops = {
.validate = phylink_generic_validate,
+ .mac_select_pcs = mtk_mac_select_pcs,
.mac_pcs_get_state = mtk_mac_pcs_get_state,
- .mac_an_restart = mtk_mac_an_restart,
.mac_config = mtk_mac_config,
+ .mac_finish = mtk_mac_finish,
.mac_link_down = mtk_mac_link_down,
.mac_link_up = mtk_mac_link_up,
};
@@ -2982,14 +3006,11 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
/* mac config is not set */
mac->interface = PHY_INTERFACE_MODE_NA;
- mac->mode = MLO_AN_PHY;
mac->speed = SPEED_UNKNOWN;
mac->phylink_config.dev = &eth->netdev[id]->dev;
mac->phylink_config.type = PHYLINK_NETDEV;
- /* This driver makes use of state->speed/state->duplex in
- * mac_config
- */
+ /* This driver makes use of state->speed in mac_config */
mac->phylink_config.legacy_pre_march2020 = true;
mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index b04977fa84f6..c1d46eb281ea 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -17,6 +17,7 @@
#include <linux/phylink.h>
#include <linux/rhashtable.h>
#include <linux/dim.h>
+#include <linux/bitfield.h>
#include "mtk_ppe.h"
#define MTK_QDMA_PAGE_SIZE 2048
@@ -493,9 +494,10 @@
#define SGMSYS_SGMII_MODE 0x20
#define SGMII_IF_MODE_BIT0 BIT(0)
#define SGMII_SPEED_DUPLEX_AN BIT(1)
-#define SGMII_SPEED_10 0x0
-#define SGMII_SPEED_100 BIT(2)
-#define SGMII_SPEED_1000 BIT(3)
+#define SGMII_SPEED_MASK GENMASK(3, 2)
+#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0)
+#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1)
+#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2)
#define SGMII_DUPLEX_FULL BIT(4)
#define SGMII_IF_MODE_BIT5 BIT(5)
#define SGMII_REMOTE_FAULT_DIS BIT(8)
@@ -867,24 +869,25 @@ struct mtk_soc_data {
/* currently no SoC has more than 2 macs */
#define MTK_MAX_DEVS 2
-#define MTK_SGMII_PHYSPEED_AN BIT(31)
-#define MTK_SGMII_PHYSPEED_MASK GENMASK(2, 0)
-#define MTK_SGMII_PHYSPEED_1000 BIT(0)
-#define MTK_SGMII_PHYSPEED_2500 BIT(1)
-#define MTK_HAS_FLAGS(flags, _x) (((flags) & (_x)) == (_x))
-
-/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
- * characteristics
+/* struct mtk_pcs - This structure holds each sgmii regmap and associated
+ * data
* @regmap: The register map pointing at the range used to setup
* SGMII modes
- * @flags: The enum refers to which mode the sgmii wants to run on
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
+ * @pcs: Phylink PCS structure
*/
+struct mtk_pcs {
+ struct regmap *regmap;
+ u32 ana_rgc3;
+ struct phylink_pcs pcs;
+};
+/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
+ * characteristics
+ * @pcs Array of individual PCS structures
+ */
struct mtk_sgmii {
- struct regmap *regmap[MTK_MAX_DEVS];
- u32 flags[MTK_MAX_DEVS];
- u32 ana_rgc3;
+ struct mtk_pcs pcs[MTK_MAX_DEVS];
};
/* struct mtk_eth - This is the main datasructure for holding the state
@@ -999,7 +1002,6 @@ struct mtk_eth {
struct mtk_mac {
int id;
phy_interface_t interface;
- unsigned int mode;
int speed;
struct device_node *of_node;
struct phylink *phylink;
@@ -1008,6 +1010,7 @@ struct mtk_mac {
struct mtk_hw_stats *hw_stats;
__be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
int hwlro_ip_cnt;
+ unsigned int syscfg0;
};
/* the struct describing the SoC. these are declared in the soc_xyz.c files */
@@ -1019,12 +1022,9 @@ void mtk_stats_update_mac(struct mtk_mac *mac);
void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg);
u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
+struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id);
int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
u32 ana_rgc3);
-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id);
-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
- const struct phylink_link_state *state);
-void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id);
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
index 1fe31058b0f2..c9353071f96a 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
@@ -90,10 +90,11 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
{
struct net_device_path_ctx ctx = {
.dev = dev,
- .daddr = addr,
};
struct net_device_path path = {};
+ memcpy(ctx.daddr, addr, sizeof(ctx.daddr));
+
if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED))
return -1;
diff --git a/drivers/net/ethernet/mediatek/mtk_sgmii.c b/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 5897940a418b..736839c84130 100644
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -9,119 +9,151 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
+#include <linux/phylink.h>
#include <linux/regmap.h>
#include "mtk_eth_soc.h"
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+static struct mtk_pcs *pcs_to_mtk_pcs(struct phylink_pcs *pcs)
{
- struct device_node *np;
- int i;
-
- ss->ana_rgc3 = ana_rgc3;
-
- for (i = 0; i < MTK_MAX_DEVS; i++) {
- np = of_parse_phandle(r, "mediatek,sgmiisys", i);
- if (!np)
- break;
-
- ss->regmap[i] = syscon_node_to_regmap(np);
- of_node_put(np);
- if (IS_ERR(ss->regmap[i]))
- return PTR_ERR(ss->regmap[i]);
- }
-
- return 0;
+ return container_of(pcs, struct mtk_pcs, pcs);
}
-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
+/* For SGMII interface mode */
+static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
{
unsigned int val;
- if (!ss->regmap[id])
- return -EINVAL;
-
/* Setup the link timer and QPHY power up inside SGMIISYS */
- regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER,
+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
SGMII_LINK_TIMER_DEFAULT);
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val |= SGMII_REMOTE_FAULT_DIS;
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
val |= SGMII_AN_RESTART;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
return 0;
+
}
-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
- const struct phylink_link_state *state)
+/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
+ * fixed speed.
+ */
+static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
+ phy_interface_t interface)
{
unsigned int val;
- if (!ss->regmap[id])
- return -EINVAL;
-
- regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
+ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
val &= ~RG_PHY_SPEED_MASK;
- if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
+ if (interface == PHY_INTERFACE_MODE_2500BASEX)
val |= RG_PHY_SPEED_3_125G;
- regmap_write(ss->regmap[id], ss->ana_rgc3, val);
+ regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
/* Disable SGMII AN */
- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
val &= ~SGMII_AN_ENABLE;
- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
-
- /* SGMII force mode setting */
- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
- val &= ~SGMII_IF_MODE_MASK;
-
- switch (state->speed) {
- case SPEED_10:
- val |= SGMII_SPEED_10;
- break;
- case SPEED_100:
- val |= SGMII_SPEED_100;
- break;
- case SPEED_2500:
- case SPEED_1000:
- val |= SGMII_SPEED_1000;
- break;
- }
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
- if (state->duplex == DUPLEX_FULL)
- val |= SGMII_DUPLEX_FULL;
-
- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ /* Set the speed etc but leave the duplex unchanged */
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
+ val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK;
+ val |= SGMII_SPEED_1000;
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
/* Release PHYA power down state */
- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
return 0;
}
-void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
+static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac)
{
- struct mtk_sgmii *ss = eth->sgmii;
- unsigned int val, sid;
+ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ int err = 0;
- /* Decide how GMAC and SGMIISYS be mapped */
- sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
- 0 : mac_id;
+ /* Setup SGMIISYS with the determined property */
+ if (interface != PHY_INTERFACE_MODE_SGMII)
+ err = mtk_pcs_setup_mode_force(mpcs, interface);
+ else if (phylink_autoneg_inband(mode))
+ err = mtk_pcs_setup_mode_an(mpcs);
- if (!ss->regmap[sid])
- return;
+ return err;
+}
+
+static void mtk_pcs_restart_an(struct phylink_pcs *pcs)
+{
+ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ unsigned int val;
- regmap_read(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, &val);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
val |= SGMII_AN_RESTART;
- regmap_write(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, val);
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
+}
+
+static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
+ phy_interface_t interface, int speed, int duplex)
+{
+ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ unsigned int val;
+
+ if (!phy_interface_mode_is_8023z(interface))
+ return;
+
+ /* SGMII force duplex setting */
+ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
+ val &= ~SGMII_DUPLEX_FULL;
+ if (duplex == DUPLEX_FULL)
+ val |= SGMII_DUPLEX_FULL;
+
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
+}
+
+static const struct phylink_pcs_ops mtk_pcs_ops = {
+ .pcs_config = mtk_pcs_config,
+ .pcs_an_restart = mtk_pcs_restart_an,
+ .pcs_link_up = mtk_pcs_link_up,
+};
+
+int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+{
+ struct device_node *np;
+ int i;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ np = of_parse_phandle(r, "mediatek,sgmiisys", i);
+ if (!np)
+ break;
+
+ ss->pcs[i].ana_rgc3 = ana_rgc3;
+ ss->pcs[i].regmap = syscon_node_to_regmap(np);
+ of_node_put(np);
+ if (IS_ERR(ss->pcs[i].regmap))
+ return PTR_ERR(ss->pcs[i].regmap);
+
+ ss->pcs[i].pcs.ops = &mtk_pcs_ops;
+ }
+
+ return 0;
+}
+
+struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id)
+{
+ if (!ss->pcs[id].regmap)
+ return NULL;
+
+ return &ss->pcs[id].pcs;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index c61dc7ae0c05..ca4b93a01034 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3417,6 +3417,9 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
dev->min_mtu = ETH_MIN_MTU;
dev->max_mtu = priv->max_mtu;
+ /* supports LSOv2 packets. */
+ netif_set_tso_max_size(dev, GSO_MAX_SIZE);
+
mdev->pndev[port] = dev;
mdev->upper[port] = NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index f777151d226f..af3b2b59a2a6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -43,6 +43,7 @@
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/indirect_call_wrapper.h>
+#include <net/ipv6.h>
#include "mlx4_en.h"
@@ -634,19 +635,28 @@ static int get_real_size(const struct sk_buff *skb,
struct net_device *dev,
int *lso_header_size,
bool *inline_ok,
- void **pfrag)
+ void **pfrag,
+ int *hopbyhop)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
int real_size;
if (shinfo->gso_size) {
*inline_ok = false;
- if (skb->encapsulation)
+ *hopbyhop = 0;
+ if (skb->encapsulation) {
*lso_header_size = (skb_inner_transport_header(skb) - skb->data) + inner_tcp_hdrlen(skb);
- else
+ } else {
+ /* Detects large IPV6 TCP packets and prepares for removal of
+ * HBH header that has been pushed by ip6_xmit(),
+ * mainly so that tcpdump can dissect them.
+ */
+ if (ipv6_has_hopopt_jumbo(skb))
+ *hopbyhop = sizeof(struct hop_jumbo_hdr);
*lso_header_size = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ }
real_size = CTRL_SIZE + shinfo->nr_frags * DS_SIZE +
- ALIGN(*lso_header_size + 4, DS_SIZE);
+ ALIGN(*lso_header_size - *hopbyhop + 4, DS_SIZE);
if (unlikely(*lso_header_size != skb_headlen(skb))) {
/* We add a segment for the skb linear buffer only if
* it contains data */
@@ -873,6 +883,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
int desc_size;
int real_size;
u32 index, bf_index;
+ struct ipv6hdr *h6;
__be32 op_own;
int lso_header_size;
void *fragptr = NULL;
@@ -881,6 +892,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
bool stop_queue;
bool inline_ok;
u8 data_offset;
+ int hopbyhop;
bool bf_ok;
tx_ind = skb_get_queue_mapping(skb);
@@ -890,7 +902,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_drop;
real_size = get_real_size(skb, shinfo, dev, &lso_header_size,
- &inline_ok, &fragptr);
+ &inline_ok, &fragptr, &hopbyhop);
if (unlikely(!real_size))
goto tx_drop_count;
@@ -943,7 +955,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
data = &tx_desc->data;
data_offset = offsetof(struct mlx4_en_tx_desc, data);
} else {
- int lso_align = ALIGN(lso_header_size + 4, DS_SIZE);
+ int lso_align = ALIGN(lso_header_size - hopbyhop + 4, DS_SIZE);
data = (void *)&tx_desc->lso + lso_align;
data_offset = offsetof(struct mlx4_en_tx_desc, lso) + lso_align;
@@ -1008,14 +1020,31 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
((ring->prod & ring->size) ?
cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0);
+ lso_header_size -= hopbyhop;
/* Fill in the LSO prefix */
tx_desc->lso.mss_hdr_size = cpu_to_be32(
shinfo->gso_size << 16 | lso_header_size);
- /* Copy headers;
- * note that we already verified that it is linear */
- memcpy(tx_desc->lso.header, skb->data, lso_header_size);
+ if (unlikely(hopbyhop)) {
+ /* remove the HBH header.
+ * Layout: [Ethernet header][IPv6 header][HBH][TCP header]
+ */
+ memcpy(tx_desc->lso.header, skb->data, ETH_HLEN + sizeof(*h6));
+ h6 = (struct ipv6hdr *)((char *)tx_desc->lso.header + ETH_HLEN);
+ h6->nexthdr = IPPROTO_TCP;
+ /* Copy the TCP header after the IPv6 one */
+ memcpy(h6 + 1,
+ skb->data + ETH_HLEN + sizeof(*h6) +
+ sizeof(struct hop_jumbo_hdr),
+ tcp_hdrlen(skb));
+ /* Leave ipv6 payload_len set to 0, as LSO v2 specs request. */
+ } else {
+ /* Copy headers;
+ * note that we already verified that it is linear
+ */
+ memcpy(tx_desc->lso.header, skb->data, lso_header_size);
+ }
ring->tso_packets++;
i = shinfo->gso_segs;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index 7895ed7cc285..9ea867a45764 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -39,7 +39,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o
mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += en/hv_vhca_stats.o
mlx5_core-$(CONFIG_MLX5_ESWITCH) += lag/mp.o lag/port_sel.o lib/geneve.o lib/port_tun.o \
en_rep.o en/rep/bond.o en/mod_hdr.o \
- en/mapping.o
+ en/mapping.o lag/mpesw.o
mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en_tc.o en/rep/tc.o en/rep/neigh.o \
lib/fs_chains.o en/tc_tun.o \
esw/indir_table.o en/tc_tun_encap.o \
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
index e52b0bac09da..6aca004e88cd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
@@ -213,12 +213,6 @@ out:
}
EXPORT_SYMBOL_GPL(mlx5_db_alloc_node);
-int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db)
-{
- return mlx5_db_alloc_node(dev, db, dev->priv.numa_node);
-}
-EXPORT_SYMBOL_GPL(mlx5_db_alloc);
-
void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db)
{
u32 db_per_page = PAGE_SIZE / cache_line_size();
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 26ba94cb432e..0377392848d9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -1887,7 +1887,8 @@ out_in:
return err;
}
-static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status, int err)
+static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status,
+ u32 syndrome, int err)
{
struct mlx5_cmd_stats *stats;
@@ -1902,6 +1903,7 @@ static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status, int
if (err == -EREMOTEIO) {
stats->failed_mbox_status++;
stats->last_failed_mbox_status = status;
+ stats->last_failed_syndrome = syndrome;
}
spin_unlock_irq(&stats->lock);
}
@@ -1909,6 +1911,7 @@ static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status, int
/* preserve -EREMOTEIO for outbox.status != OK, otherwise return err as is */
static int cmd_status_err(struct mlx5_core_dev *dev, int err, u16 opcode, void *out)
{
+ u32 syndrome = MLX5_GET(mbox_out, out, syndrome);
u8 status = MLX5_GET(mbox_out, out, status);
if (err == -EREMOTEIO) /* -EREMOTEIO is preserved */
@@ -1917,7 +1920,7 @@ static int cmd_status_err(struct mlx5_core_dev *dev, int err, u16 opcode, void *
if (!err && status != MLX5_CMD_STAT_OK)
err = -EREMOTEIO;
- cmd_status_log(dev, opcode, status, err);
+ cmd_status_log(dev, opcode, status, syndrome, err);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
index 3d3e55a5cb11..9caa1b52321b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
@@ -192,6 +192,8 @@ void mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev)
&stats->last_failed_errno);
debugfs_create_u8("last_failed_mbox_status", 0400, stats->root,
&stats->last_failed_mbox_status);
+ debugfs_create_x32("last_failed_syndrome", 0400, stats->root,
+ &stats->last_failed_syndrome);
}
}
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index b90902db7819..65d3c4865abf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -1220,6 +1220,7 @@ mlx5e_tx_mpwqe_supported(struct mlx5_core_dev *mdev)
MLX5_CAP_ETH(mdev, enhanced_multi_pkt_send_wqe);
}
+int mlx5e_get_pf_num_tirs(struct mlx5_core_dev *mdev);
int mlx5e_priv_init(struct mlx5e_priv *priv,
const struct mlx5e_profile *profile,
struct net_device *netdev,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
index 3c1edfa33aa7..68364484a435 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c
@@ -565,8 +565,7 @@ static void mlx5e_build_rx_cq_param(struct mlx5_core_dev *mdev,
static u8 rq_end_pad_mode(struct mlx5_core_dev *mdev, struct mlx5e_params *params)
{
bool lro_en = params->packet_merge.type == MLX5E_PACKET_MERGE_LRO;
- bool ro = pcie_relaxed_ordering_enabled(mdev->pdev) &&
- MLX5_CAP_GEN(mdev, relaxed_ordering_write);
+ bool ro = MLX5_CAP_GEN(mdev, relaxed_ordering_write);
return ro && lro_en ?
MLX5_WQ_END_PAD_MODE_NONE : MLX5_WQ_END_PAD_MODE_ALIGN;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c
index 2b002c6a2e73..4ac7de3f6afa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c
@@ -10,6 +10,7 @@
#include "en/tc_tun_encap.h"
#include "en/tc_priv.h"
#include "en_rep.h"
+#include "lag/lag.h"
static bool
same_vf_reps(struct mlx5e_priv *priv, struct net_device *out_dev)
@@ -215,6 +216,7 @@ parse_mirred(struct mlx5e_tc_act_parse_state *parse_state,
struct net_device *uplink_dev;
struct mlx5e_priv *out_priv;
struct mlx5_eswitch *esw;
+ bool is_uplink_rep;
int *ifindexes;
int if_count;
int err;
@@ -229,6 +231,10 @@ parse_mirred(struct mlx5e_tc_act_parse_state *parse_state,
parse_state->ifindexes[if_count] = out_dev->ifindex;
parse_state->if_count++;
+ is_uplink_rep = mlx5e_eswitch_uplink_rep(out_dev);
+ err = mlx5_lag_do_mirred(priv->mdev, out_dev);
+ if (err)
+ return err;
out_dev = get_fdb_out_dev(uplink_dev, out_dev);
if (!out_dev)
@@ -268,6 +274,14 @@ parse_mirred(struct mlx5e_tc_act_parse_state *parse_state,
rpriv = out_priv->ppriv;
esw_attr->dests[esw_attr->out_count].rep = rpriv->rep;
esw_attr->dests[esw_attr->out_count].mdev = out_priv->mdev;
+
+ /* If output device is bond master then rules are not explicit
+ * so we don't attempt to count them.
+ */
+ if (is_uplink_rep && MLX5_CAP_PORT_SELECTION(priv->mdev, port_select_flow_table) &&
+ MLX5_CAP_GEN(priv->mdev, create_lag_when_not_master_up))
+ attr->lag.count = true;
+
esw_attr->out_count++;
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c
index b979826f3f6c..2b80fe73549d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c
@@ -23,7 +23,7 @@ struct mlx5_ct_fs_smfs_matcher {
};
struct mlx5_ct_fs_smfs_matchers {
- struct mlx5_ct_fs_smfs_matcher smfs_matchers[4];
+ struct mlx5_ct_fs_smfs_matcher smfs_matchers[6];
struct list_head used;
};
@@ -44,7 +44,8 @@ struct mlx5_ct_fs_smfs_rule {
};
static inline void
-mlx5_ct_fs_smfs_fill_mask(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec, bool ipv4, bool tcp)
+mlx5_ct_fs_smfs_fill_mask(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec, bool ipv4, bool tcp,
+ bool gre)
{
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, outer_headers);
@@ -77,7 +78,7 @@ mlx5_ct_fs_smfs_fill_mask(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec, bo
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, tcp_dport);
MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags,
ntohs(MLX5_CT_TCP_FLAGS_MASK));
- } else {
+ } else if (!gre) {
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, udp_sport);
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, udp_dport);
}
@@ -87,7 +88,7 @@ mlx5_ct_fs_smfs_fill_mask(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec, bo
static struct mlx5dr_matcher *
mlx5_ct_fs_smfs_matcher_create(struct mlx5_ct_fs *fs, struct mlx5dr_table *tbl, bool ipv4,
- bool tcp, u32 priority)
+ bool tcp, bool gre, u32 priority)
{
struct mlx5dr_matcher *dr_matcher;
struct mlx5_flow_spec *spec;
@@ -96,7 +97,7 @@ mlx5_ct_fs_smfs_matcher_create(struct mlx5_ct_fs *fs, struct mlx5dr_table *tbl,
if (!spec)
return ERR_PTR(-ENOMEM);
- mlx5_ct_fs_smfs_fill_mask(fs, spec, ipv4, tcp);
+ mlx5_ct_fs_smfs_fill_mask(fs, spec, ipv4, tcp, gre);
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2 | MLX5_MATCH_OUTER_HEADERS;
dr_matcher = mlx5_smfs_matcher_create(tbl, priority, spec);
@@ -108,7 +109,7 @@ mlx5_ct_fs_smfs_matcher_create(struct mlx5_ct_fs *fs, struct mlx5dr_table *tbl,
}
static struct mlx5_ct_fs_smfs_matcher *
-mlx5_ct_fs_smfs_matcher_get(struct mlx5_ct_fs *fs, bool nat, bool ipv4, bool tcp)
+mlx5_ct_fs_smfs_matcher_get(struct mlx5_ct_fs *fs, bool nat, bool ipv4, bool tcp, bool gre)
{
struct mlx5_ct_fs_smfs *fs_smfs = mlx5_ct_fs_priv(fs);
struct mlx5_ct_fs_smfs_matcher *m, *smfs_matcher;
@@ -119,7 +120,7 @@ mlx5_ct_fs_smfs_matcher_get(struct mlx5_ct_fs *fs, bool nat, bool ipv4, bool tcp
int prio;
matchers = nat ? &fs_smfs->matchers_nat : &fs_smfs->matchers;
- smfs_matcher = &matchers->smfs_matchers[ipv4 * 2 + tcp];
+ smfs_matcher = &matchers->smfs_matchers[ipv4 * 3 + tcp * 2 + gre];
if (refcount_inc_not_zero(&smfs_matcher->ref))
return smfs_matcher;
@@ -145,11 +146,11 @@ mlx5_ct_fs_smfs_matcher_get(struct mlx5_ct_fs *fs, bool nat, bool ipv4, bool tcp
}
tbl = nat ? fs_smfs->ct_nat_tbl : fs_smfs->ct_tbl;
- dr_matcher = mlx5_ct_fs_smfs_matcher_create(fs, tbl, ipv4, tcp, prio);
+ dr_matcher = mlx5_ct_fs_smfs_matcher_create(fs, tbl, ipv4, tcp, gre, prio);
if (IS_ERR(dr_matcher)) {
netdev_warn(fs->netdev,
- "ct_fs_smfs: failed to create matcher (nat %d, ipv4 %d, tcp %d), err: %ld\n",
- nat, ipv4, tcp, PTR_ERR(dr_matcher));
+ "ct_fs_smfs: failed to create matcher (nat %d, ipv4 %d, tcp %d, gre %d), err: %ld\n",
+ nat, ipv4, tcp, gre, PTR_ERR(dr_matcher));
smfs_matcher = ERR_CAST(dr_matcher);
goto out_unlock;
@@ -222,16 +223,17 @@ mlx5_ct_fs_smfs_destroy(struct mlx5_ct_fs *fs)
static inline bool
mlx5_tc_ct_valid_used_dissector_keys(const u32 used_keys)
{
-#define DISSECTOR_BIT(name) BIT(FLOW_DISSECTOR_KEY_ ## name)
- const u32 basic_keys = DISSECTOR_BIT(BASIC) | DISSECTOR_BIT(CONTROL) |
- DISSECTOR_BIT(PORTS) | DISSECTOR_BIT(META);
- const u32 ipv4_tcp = basic_keys | DISSECTOR_BIT(IPV4_ADDRS) | DISSECTOR_BIT(TCP);
- const u32 ipv4_udp = basic_keys | DISSECTOR_BIT(IPV4_ADDRS);
- const u32 ipv6_tcp = basic_keys | DISSECTOR_BIT(IPV6_ADDRS) | DISSECTOR_BIT(TCP);
- const u32 ipv6_udp = basic_keys | DISSECTOR_BIT(IPV6_ADDRS);
+#define DISS_BIT(name) BIT(FLOW_DISSECTOR_KEY_ ## name)
+ const u32 basic_keys = DISS_BIT(BASIC) | DISS_BIT(CONTROL) | DISS_BIT(META);
+ const u32 ipv4_tcp = basic_keys | DISS_BIT(IPV4_ADDRS) | DISS_BIT(PORTS) | DISS_BIT(TCP);
+ const u32 ipv6_tcp = basic_keys | DISS_BIT(IPV6_ADDRS) | DISS_BIT(PORTS) | DISS_BIT(TCP);
+ const u32 ipv4_udp = basic_keys | DISS_BIT(IPV4_ADDRS) | DISS_BIT(PORTS);
+ const u32 ipv6_udp = basic_keys | DISS_BIT(IPV6_ADDRS) | DISS_BIT(PORTS);
+ const u32 ipv4_gre = basic_keys | DISS_BIT(IPV4_ADDRS);
+ const u32 ipv6_gre = basic_keys | DISS_BIT(IPV6_ADDRS);
return (used_keys == ipv4_tcp || used_keys == ipv4_udp || used_keys == ipv6_tcp ||
- used_keys == ipv6_udp);
+ used_keys == ipv6_udp || used_keys == ipv4_gre || used_keys == ipv6_gre);
}
static bool
@@ -254,20 +256,24 @@ mlx5_ct_fs_smfs_ct_validate_flow_rule(struct mlx5_ct_fs *fs, struct flow_rule *f
flow_rule_match_control(flow_rule, &control);
flow_rule_match_ipv4_addrs(flow_rule, &ipv4_addrs);
flow_rule_match_ipv6_addrs(flow_rule, &ipv6_addrs);
- flow_rule_match_ports(flow_rule, &ports);
- flow_rule_match_tcp(flow_rule, &tcp);
+ if (basic.key->ip_proto != IPPROTO_GRE)
+ flow_rule_match_ports(flow_rule, &ports);
+ if (basic.key->ip_proto == IPPROTO_TCP)
+ flow_rule_match_tcp(flow_rule, &tcp);
if (basic.mask->n_proto != htons(0xFFFF) ||
(basic.key->n_proto != htons(ETH_P_IP) && basic.key->n_proto != htons(ETH_P_IPV6)) ||
basic.mask->ip_proto != 0xFF ||
- (basic.key->ip_proto != IPPROTO_UDP && basic.key->ip_proto != IPPROTO_TCP)) {
+ (basic.key->ip_proto != IPPROTO_UDP && basic.key->ip_proto != IPPROTO_TCP &&
+ basic.key->ip_proto != IPPROTO_GRE)) {
ct_dbg("rule uses unexpected basic match (n_proto 0x%04x/0x%04x, ip_proto 0x%02x/0x%02x)",
ntohs(basic.key->n_proto), ntohs(basic.mask->n_proto),
basic.key->ip_proto, basic.mask->ip_proto);
return false;
}
- if (ports.mask->src != htons(0xFFFF) || ports.mask->dst != htons(0xFFFF)) {
+ if (basic.key->ip_proto != IPPROTO_GRE &&
+ (ports.mask->src != htons(0xFFFF) || ports.mask->dst != htons(0xFFFF))) {
ct_dbg("rule uses ports match (src 0x%04x, dst 0x%04x)",
ports.mask->src, ports.mask->dst);
return false;
@@ -291,7 +297,7 @@ mlx5_ct_fs_smfs_ct_rule_add(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec,
struct mlx5dr_action *actions[5];
struct mlx5dr_rule *rule;
int num_actions = 0, err;
- bool nat, tcp, ipv4;
+ bool nat, tcp, ipv4, gre;
if (!mlx5_ct_fs_smfs_ct_validate_flow_rule(fs, flow_rule))
return ERR_PTR(-EOPNOTSUPP);
@@ -314,15 +320,17 @@ mlx5_ct_fs_smfs_ct_rule_add(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec,
ipv4 = mlx5e_tc_get_ip_version(spec, true) == 4;
tcp = MLX5_GET(fte_match_param, spec->match_value,
outer_headers.ip_protocol) == IPPROTO_TCP;
+ gre = MLX5_GET(fte_match_param, spec->match_value,
+ outer_headers.ip_protocol) == IPPROTO_GRE;
- smfs_matcher = mlx5_ct_fs_smfs_matcher_get(fs, nat, ipv4, tcp);
+ smfs_matcher = mlx5_ct_fs_smfs_matcher_get(fs, nat, ipv4, tcp, gre);
if (IS_ERR(smfs_matcher)) {
err = PTR_ERR(smfs_matcher);
goto err_matcher;
}
rule = mlx5_smfs_rule_create(smfs_matcher->dr_matcher, spec, num_actions, actions,
- MLX5_FLOW_CONTEXT_FLOW_SOURCE_ANY_VPORT);
+ spec->flow_context.flow_source);
if (!rule) {
err = -EINVAL;
goto err_create;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
index 228fbd2c20d4..bceea7a1589e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
@@ -15,6 +15,7 @@
#include <linux/refcount.h>
#include <linux/xarray.h>
#include <linux/if_macvlan.h>
+#include <linux/debugfs.h>
#include "lib/fs_chains.h"
#include "en/tc_ct.h"
@@ -47,6 +48,15 @@
#define ct_dbg(fmt, args...)\
netdev_dbg(ct_priv->netdev, "ct_debug: " fmt "\n", ##args)
+struct mlx5_tc_ct_debugfs {
+ struct {
+ atomic_t offloaded;
+ atomic_t rx_dropped;
+ } stats;
+
+ struct dentry *root;
+};
+
struct mlx5_tc_ct_priv {
struct mlx5_core_dev *dev;
const struct net_device *netdev;
@@ -66,6 +76,8 @@ struct mlx5_tc_ct_priv {
struct mlx5_ct_fs *fs;
struct mlx5_ct_fs_ops *fs_ops;
spinlock_t ht_lock; /* protects ft entries */
+
+ struct mlx5_tc_ct_debugfs debugfs;
};
struct mlx5_ct_flow {
@@ -520,6 +532,8 @@ mlx5_tc_ct_entry_del_rules(struct mlx5_tc_ct_priv *ct_priv,
{
mlx5_tc_ct_entry_del_rule(ct_priv, entry, true);
mlx5_tc_ct_entry_del_rule(ct_priv, entry, false);
+
+ atomic_dec(&ct_priv->debugfs.stats.offloaded);
}
static struct flow_action_entry *
@@ -1040,6 +1054,7 @@ mlx5_tc_ct_entry_add_rules(struct mlx5_tc_ct_priv *ct_priv,
if (err)
goto err_nat;
+ atomic_inc(&ct_priv->debugfs.stats.offloaded);
return 0;
err_nat:
@@ -2064,6 +2079,29 @@ out_err:
return err;
}
+static void
+mlx5_ct_tc_create_dbgfs(struct mlx5_tc_ct_priv *ct_priv)
+{
+ bool is_fdb = ct_priv->ns_type == MLX5_FLOW_NAMESPACE_FDB;
+ struct mlx5_tc_ct_debugfs *ct_dbgfs = &ct_priv->debugfs;
+ char dirname[16] = {};
+
+ if (sscanf(dirname, "ct_%s", is_fdb ? "fdb" : "nic") < 0)
+ return;
+
+ ct_dbgfs->root = debugfs_create_dir(dirname, mlx5_debugfs_get_dev_root(ct_priv->dev));
+ debugfs_create_atomic_t("offloaded", 0400, ct_dbgfs->root,
+ &ct_dbgfs->stats.offloaded);
+ debugfs_create_atomic_t("rx_dropped", 0400, ct_dbgfs->root,
+ &ct_dbgfs->stats.rx_dropped);
+}
+
+static void
+mlx5_ct_tc_remove_dbgfs(struct mlx5_tc_ct_priv *ct_priv)
+{
+ debugfs_remove_recursive(ct_priv->debugfs.root);
+}
+
#define INIT_ERR_PREFIX "tc ct offload init failed"
struct mlx5_tc_ct_priv *
@@ -2139,6 +2177,7 @@ mlx5_tc_ct_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains,
if (err)
goto err_init_fs;
+ mlx5_ct_tc_create_dbgfs(ct_priv);
return ct_priv;
err_init_fs:
@@ -2171,6 +2210,7 @@ mlx5_tc_ct_clean(struct mlx5_tc_ct_priv *ct_priv)
if (!ct_priv)
return;
+ mlx5_ct_tc_remove_dbgfs(ct_priv);
chains = ct_priv->chains;
ct_priv->fs_ops->destroy(ct_priv->fs);
@@ -2200,22 +2240,22 @@ mlx5e_tc_ct_restore_flow(struct mlx5_tc_ct_priv *ct_priv,
return true;
if (mapping_find(ct_priv->zone_mapping, zone_restore_id, &zone))
- return false;
+ goto out_inc_drop;
if (!mlx5_tc_ct_skb_to_tuple(skb, &tuple, zone))
- return false;
+ goto out_inc_drop;
spin_lock(&ct_priv->ht_lock);
entry = mlx5_tc_ct_entry_get(ct_priv, &tuple);
if (!entry) {
spin_unlock(&ct_priv->ht_lock);
- return false;
+ goto out_inc_drop;
}
if (IS_ERR(entry)) {
spin_unlock(&ct_priv->ht_lock);
- return false;
+ goto out_inc_drop;
}
spin_unlock(&ct_priv->ht_lock);
@@ -2223,4 +2263,8 @@ mlx5e_tc_ct_restore_flow(struct mlx5_tc_ct_priv *ct_priv,
__mlx5_tc_ct_entry_put(entry);
return true;
+
+out_inc_drop:
+ atomic_inc(&ct_priv->debugfs.stats.rx_dropped);
+ return false;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c
index a55b066746cb..857840ab1e91 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c
@@ -14,19 +14,26 @@ static int mlx5e_trap_napi_poll(struct napi_struct *napi, int budget)
bool busy = false;
int work_done = 0;
+ rcu_read_lock();
+
ch_stats->poll++;
work_done = mlx5e_poll_rx_cq(&rq->cq, budget);
busy |= work_done == budget;
busy |= rq->post_wqes(rq);
- if (busy)
- return budget;
+ if (busy) {
+ work_done = budget;
+ goto out;
+ }
if (unlikely(!napi_complete_done(napi, work_done)))
- return work_done;
+ goto out;
mlx5e_cq_arm(&rq->cq);
+
+out:
+ rcu_read_unlock();
return work_done;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
index c0f409c195bf..43a536cb81db 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
@@ -38,12 +38,11 @@
void mlx5e_mkey_set_relaxed_ordering(struct mlx5_core_dev *mdev, void *mkc)
{
- bool ro_pci_enable = pcie_relaxed_ordering_enabled(mdev->pdev);
bool ro_write = MLX5_CAP_GEN(mdev, relaxed_ordering_write);
bool ro_read = MLX5_CAP_GEN(mdev, relaxed_ordering_read);
- MLX5_SET(mkc, mkc, relaxed_ordering_read, ro_pci_enable && ro_read);
- MLX5_SET(mkc, mkc, relaxed_ordering_write, ro_pci_enable && ro_write);
+ MLX5_SET(mkc, mkc, relaxed_ordering_read, ro_read);
+ MLX5_SET(mkc, mkc, relaxed_ordering_write, ro_write);
}
static int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
index aeff1d972a46..d2f0773f95c6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -155,7 +155,7 @@ static int mlx5e_vport_context_update_vlans(struct mlx5e_priv *priv)
list_size = max_list_size;
}
- vlans = kcalloc(list_size, sizeof(*vlans), GFP_KERNEL);
+ vlans = kvcalloc(list_size, sizeof(*vlans), GFP_KERNEL);
if (!vlans)
return -ENOMEM;
@@ -171,7 +171,7 @@ static int mlx5e_vport_context_update_vlans(struct mlx5e_priv *priv)
netdev_err(ndev, "Failed to modify vport vlans list err(%d)\n",
err);
- kfree(vlans);
+ kvfree(vlans);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index d27986869b8b..05c015515cce 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3858,6 +3858,10 @@ static netdev_features_t mlx5e_fix_uplink_rep_features(struct net_device *netdev
if (netdev->features & NETIF_F_NTUPLE)
netdev_warn(netdev, "Disabling ntuple, not supported in switchdev mode\n");
+ features &= ~NETIF_F_GRO_HW;
+ if (netdev->features & NETIF_F_GRO_HW)
+ netdev_warn(netdev, "Disabling HW_GRO, not supported in switchdev mode\n");
+
return features;
}
@@ -3890,6 +3894,25 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
}
}
+ if (params->xdp_prog) {
+ if (features & NETIF_F_LRO) {
+ netdev_warn(netdev, "LRO is incompatible with XDP\n");
+ features &= ~NETIF_F_LRO;
+ }
+ if (features & NETIF_F_GRO_HW) {
+ netdev_warn(netdev, "HW GRO is incompatible with XDP\n");
+ features &= ~NETIF_F_GRO_HW;
+ }
+ }
+
+ if (priv->xsk.refcnt) {
+ if (features & NETIF_F_GRO_HW) {
+ netdev_warn(netdev, "HW GRO is incompatible with AF_XDP (%u XSKs are active)\n",
+ priv->xsk.refcnt);
+ features &= ~NETIF_F_GRO_HW;
+ }
+ }
+
if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
features &= ~NETIF_F_RXHASH;
if (netdev->features & NETIF_F_RXHASH)
@@ -4812,6 +4835,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
netdev->vlan_features |= NETIF_F_TSO6;
netdev->vlan_features |= NETIF_F_RXCSUM;
netdev->vlan_features |= NETIF_F_RXHASH;
+ netdev->vlan_features |= NETIF_F_GSO_PARTIAL;
netdev->mpls_features |= NETIF_F_SG;
netdev->mpls_features |= NETIF_F_HW_CSUM;
@@ -4838,10 +4862,6 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
netdev->hw_features |= NETIF_F_HW_VLAN_STAG_TX;
- if (!!MLX5_CAP_GEN(mdev, shampo) &&
- mlx5e_check_fragmented_striding_rq_cap(mdev))
- netdev->hw_features |= NETIF_F_GRO_HW;
-
if (mlx5e_tunnel_any_tx_proto_supported(mdev)) {
netdev->hw_enc_features |= NETIF_F_HW_CSUM;
netdev->hw_enc_features |= NETIF_F_TSO;
@@ -4877,7 +4897,6 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
NETIF_F_GSO_IPXIP6;
}
- netdev->hw_features |= NETIF_F_GSO_PARTIAL;
netdev->gso_partial_features |= NETIF_F_GSO_UDP_L4;
netdev->hw_features |= NETIF_F_GSO_UDP_L4;
netdev->features |= NETIF_F_GSO_UDP_L4;
@@ -4920,6 +4939,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
netdev->priv_flags |= IFF_UNICAST_FLT;
+ netif_set_tso_max_size(netdev, GSO_MAX_SIZE);
mlx5e_set_netdev_dev_addr(netdev);
mlx5e_ipsec_build_netdev(priv);
mlx5e_ktls_build_netdev(priv);
@@ -5220,6 +5240,15 @@ mlx5e_calc_max_nch(struct mlx5_core_dev *mdev, struct net_device *netdev,
return max_nch;
}
+int mlx5e_get_pf_num_tirs(struct mlx5_core_dev *mdev)
+{
+ /* Indirect TIRS: 2 sets of TTCs (inner + outer steering)
+ * and 1 set of direct TIRS
+ */
+ return 2 * MLX5E_NUM_INDIR_TIRS
+ + mlx5e_profile_max_num_channels(mdev, &mlx5e_nic_profile);
+}
+
/* mlx5e generic netdev management API (move to en_common.c) */
int mlx5e_priv_init(struct mlx5e_priv *priv,
const struct mlx5e_profile *profile,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 47f7b4c034cc..eb90e79388f1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -399,7 +399,9 @@ out_err:
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;
+ bool is_uplink_rep = mlx5e_is_uplink_rep(priv);
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *rep = rpriv->rep;
int n, tc, nch, num_sqs = 0;
@@ -411,9 +413,13 @@ int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
ptp_sq = !!(priv->channels.ptp &&
MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_TX_PORT_TS));
nch = priv->channels.num + ptp_sq;
+ /* +2 for xdpsqs, they don't exist on the ptp channel but will not be
+ * counted for by num_sqs.
+ */
+ if (is_uplink_rep)
+ sqs_per_channel += 2;
- sqs = kcalloc(nch * mlx5e_get_dcb_num_tc(&priv->channels.params), sizeof(*sqs),
- GFP_KERNEL);
+ sqs = kvcalloc(nch * sqs_per_channel, sizeof(*sqs), GFP_KERNEL);
if (!sqs)
goto out;
@@ -421,6 +427,13 @@ int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
c = priv->channels.c[n];
for (tc = 0; tc < c->num_tc; tc++)
sqs[num_sqs++] = c->sq[tc].sqn;
+
+ if (is_uplink_rep) {
+ if (c->xdp)
+ sqs[num_sqs++] = c->rq_xdpsq.sqn;
+
+ sqs[num_sqs++] = c->xdpsq.sqn;
+ }
}
if (ptp_sq) {
struct mlx5e_ptp *ptp_ch = priv->channels.ptp;
@@ -430,7 +443,7 @@ int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
}
err = mlx5e_sqs2vport_start(esw, rep, sqs, num_sqs);
- kfree(sqs);
+ kvfree(sqs);
out:
if (err)
@@ -604,10 +617,16 @@ bool mlx5e_eswitch_vf_rep(const struct net_device *netdev)
return netdev->netdev_ops == &mlx5e_netdev_ops_rep;
}
+/* One indirect TIR set for outer. Inner not supported in reps. */
+#define REP_NUM_INDIR_TIRS MLX5E_NUM_INDIR_TIRS
+
static int mlx5e_rep_max_nch_limit(struct mlx5_core_dev *mdev)
{
- return (1 << MLX5_CAP_GEN(mdev, log_max_tir)) /
- mlx5_eswitch_get_total_vports(mdev);
+ int max_tir_num = 1 << MLX5_CAP_GEN(mdev, log_max_tir);
+ int num_vports = mlx5_eswitch_get_total_vports(mdev);
+
+ return (max_tir_num - mlx5e_get_pf_num_tirs(mdev)
+ - (num_vports * REP_NUM_INDIR_TIRS)) / num_vports;
}
static void mlx5e_build_rep_params(struct net_device *netdev)
@@ -1269,7 +1288,7 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
struct mlx5e_rep_priv *rpriv;
int err;
- rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
+ rpriv = kvzalloc(sizeof(*rpriv), GFP_KERNEL);
if (!rpriv)
return -ENOMEM;
@@ -1284,7 +1303,7 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
err = mlx5e_vport_vf_rep_load(dev, rep);
if (err)
- kfree(rpriv);
+ kvfree(rpriv);
return err;
}
@@ -1312,7 +1331,7 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
priv->profile->cleanup(priv);
mlx5e_destroy_netdev(priv);
free_ppriv:
- kfree(ppriv); /* mlx5e_rep_priv */
+ kvfree(ppriv); /* mlx5e_rep_priv */
}
static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index fb11081001a0..24de37b79f5a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -2038,7 +2038,7 @@ mlx5e_hw_gro_skb_has_enough_space(struct sk_buff *skb, u16 data_bcnt)
{
int nr_frags = skb_shinfo(skb)->nr_frags;
- return PAGE_SIZE * nr_frags + data_bcnt <= GSO_MAX_SIZE;
+ return PAGE_SIZE * nr_frags + data_bcnt <= GRO_LEGACY_MAX_SIZE;
}
static void
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index ac0f73074f7a..49dea02a12d2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -1740,6 +1740,9 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
free_flow_post_acts(flow);
+ if (flow->attr->lag.count)
+ mlx5_lag_del_mpesw_rule(esw->dev);
+
kvfree(attr->esw_attr->rx_tun_attr);
kvfree(attr->parse_attr);
kfree(flow->attr);
@@ -3788,12 +3791,25 @@ static bool is_lag_dev(struct mlx5e_priv *priv,
same_hw_reps(priv, peer_netdev));
}
+static bool is_multiport_eligible(struct mlx5e_priv *priv, struct net_device *out_dev)
+{
+ if (mlx5e_eswitch_uplink_rep(out_dev) &&
+ MLX5_CAP_PORT_SELECTION(priv->mdev, port_select_flow_table) &&
+ MLX5_CAP_GEN(priv->mdev, create_lag_when_not_master_up))
+ return true;
+
+ return false;
+}
+
bool mlx5e_is_valid_eswitch_fwd_dev(struct mlx5e_priv *priv,
struct net_device *out_dev)
{
if (is_merged_eswitch_vfs(priv, out_dev))
return true;
+ if (is_multiport_eligible(priv, out_dev))
+ return true;
+
if (is_lag_dev(priv, out_dev))
return true;
@@ -4050,6 +4066,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
struct mlx5_core_dev *in_mdev)
{
struct flow_rule *rule = flow_cls_offload_flow_rule(f);
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct netlink_ext_ack *extack = f->common.extack;
struct mlx5e_tc_flow_parse_attr *parse_attr;
struct mlx5e_tc_flow *flow;
@@ -4085,17 +4102,26 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
if (err)
goto err_free;
+ if (flow->attr->lag.count) {
+ err = mlx5_lag_add_mpesw_rule(esw->dev);
+ if (err)
+ goto err_free;
+ }
+
err = mlx5e_tc_add_fdb_flow(priv, flow, extack);
complete_all(&flow->init_done);
if (err) {
if (!(err == -ENETUNREACH && mlx5_lag_is_multipath(in_mdev)))
- goto err_free;
+ goto err_lag;
add_unready_flow(flow);
}
return flow;
+err_lag:
+ if (flow->attr->lag.count)
+ mlx5_lag_del_mpesw_rule(esw->dev);
err_free:
mlx5e_flow_put(priv, flow);
out:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
index a80b00946f1b..e2a1250aeca1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
@@ -85,6 +85,13 @@ struct mlx5_flow_attr {
u32 flags;
struct list_head list;
struct mlx5e_post_act_handle *post_act_handle;
+ struct {
+ /* Indicate whether the parsed flow should be counted for lag mode decision
+ * making
+ */
+ bool count;
+ } lag;
+ /* keep this union last */
union {
struct mlx5_esw_flow_attr esw_attr[0];
struct mlx5_nic_flow_attr nic_attr[0];
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
index 5855d8f9c509..50d14cec4894 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
@@ -40,6 +40,7 @@
#include "en_accel/en_accel.h"
#include "en_accel/ipsec_rxtx.h"
#include "en/ptp.h"
+#include <net/ipv6.h>
static void mlx5e_dma_unmap_wqe_err(struct mlx5e_txqsq *sq, u8 num_dma)
{
@@ -91,6 +92,13 @@ static inline u16 mlx5e_calc_min_inline(enum mlx5_inline_modes mode,
return min_t(u16, hlen, skb_headlen(skb));
}
+#define MLX5_UNSAFE_MEMCPY_DISCLAIMER \
+ "This copy has been bounds-checked earlier in " \
+ "mlx5i_sq_calc_wqe_attr() and intentionally " \
+ "crosses a flex array boundary. Since it is " \
+ "performance sensitive, splitting the copy is " \
+ "undesirable."
+
static inline void mlx5e_insert_vlan(void *start, struct sk_buff *skb, u16 ihs)
{
struct vlan_ethhdr *vhdr = (struct vlan_ethhdr *)start;
@@ -100,7 +108,10 @@ static inline void mlx5e_insert_vlan(void *start, struct sk_buff *skb, u16 ihs)
memcpy(&vhdr->addrs, skb->data, cpy1_sz);
vhdr->h_vlan_proto = skb->vlan_proto;
vhdr->h_vlan_TCI = cpu_to_be16(skb_vlan_tag_get(skb));
- memcpy(&vhdr->h_vlan_encapsulated_proto, skb->data + cpy1_sz, cpy2_sz);
+ unsafe_memcpy(&vhdr->h_vlan_encapsulated_proto,
+ skb->data + cpy1_sz,
+ cpy2_sz,
+ MLX5_UNSAFE_MEMCPY_DISCLAIMER);
}
static inline void
@@ -130,23 +141,32 @@ mlx5e_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
sq->stats->csum_none++;
}
+/* Returns the number of header bytes that we plan
+ * to inline later in the transmit descriptor
+ */
static inline u16
-mlx5e_tx_get_gso_ihs(struct mlx5e_txqsq *sq, struct sk_buff *skb)
+mlx5e_tx_get_gso_ihs(struct mlx5e_txqsq *sq, struct sk_buff *skb, int *hopbyhop)
{
struct mlx5e_sq_stats *stats = sq->stats;
u16 ihs;
+ *hopbyhop = 0;
if (skb->encapsulation) {
ihs = skb_inner_transport_offset(skb) + inner_tcp_hdrlen(skb);
stats->tso_inner_packets++;
stats->tso_inner_bytes += skb->len - ihs;
} else {
- if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
+ if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
ihs = skb_transport_offset(skb) + sizeof(struct udphdr);
- else
+ } else {
ihs = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ if (ipv6_has_hopopt_jumbo(skb)) {
+ *hopbyhop = sizeof(struct hop_jumbo_hdr);
+ ihs -= sizeof(struct hop_jumbo_hdr);
+ }
+ }
stats->tso_packets++;
- stats->tso_bytes += skb->len - ihs;
+ stats->tso_bytes += skb->len - ihs - *hopbyhop;
}
return ihs;
@@ -208,6 +228,7 @@ struct mlx5e_tx_attr {
__be16 mss;
u16 insz;
u8 opcode;
+ u8 hopbyhop;
};
struct mlx5e_tx_wqe_attr {
@@ -244,14 +265,16 @@ static void mlx5e_sq_xmit_prepare(struct mlx5e_txqsq *sq, struct sk_buff *skb,
struct mlx5e_sq_stats *stats = sq->stats;
if (skb_is_gso(skb)) {
- u16 ihs = mlx5e_tx_get_gso_ihs(sq, skb);
+ int hopbyhop;
+ u16 ihs = mlx5e_tx_get_gso_ihs(sq, skb, &hopbyhop);
*attr = (struct mlx5e_tx_attr) {
.opcode = MLX5_OPCODE_LSO,
.mss = cpu_to_be16(skb_shinfo(skb)->gso_size),
.ihs = ihs,
.num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs,
- .headlen = skb_headlen(skb) - ihs,
+ .headlen = skb_headlen(skb) - ihs - hopbyhop,
+ .hopbyhop = hopbyhop,
};
stats->packets += skb_shinfo(skb)->gso_segs;
@@ -365,7 +388,8 @@ mlx5e_sq_xmit_wqe(struct mlx5e_txqsq *sq, struct sk_buff *skb,
struct mlx5_wqe_eth_seg *eseg;
struct mlx5_wqe_data_seg *dseg;
struct mlx5e_tx_wqe_info *wi;
-
+ u16 ihs = attr->ihs;
+ struct ipv6hdr *h6;
struct mlx5e_sq_stats *stats = sq->stats;
int num_dma;
@@ -379,21 +403,40 @@ mlx5e_sq_xmit_wqe(struct mlx5e_txqsq *sq, struct sk_buff *skb,
eseg->mss = attr->mss;
- if (attr->ihs) {
- if (skb_vlan_tag_present(skb)) {
- eseg->inline_hdr.sz |= cpu_to_be16(attr->ihs + VLAN_HLEN);
- mlx5e_insert_vlan(eseg->inline_hdr.start, skb, attr->ihs);
+ if (ihs) {
+ u8 *start = eseg->inline_hdr.start;
+
+ if (unlikely(attr->hopbyhop)) {
+ /* remove the HBH header.
+ * Layout: [Ethernet header][IPv6 header][HBH][TCP header]
+ */
+ if (skb_vlan_tag_present(skb)) {
+ mlx5e_insert_vlan(start, skb, ETH_HLEN + sizeof(*h6));
+ ihs += VLAN_HLEN;
+ h6 = (struct ipv6hdr *)(start + sizeof(struct vlan_ethhdr));
+ } else {
+ unsafe_memcpy(start, skb->data,
+ ETH_HLEN + sizeof(*h6),
+ MLX5_UNSAFE_MEMCPY_DISCLAIMER);
+ h6 = (struct ipv6hdr *)(start + ETH_HLEN);
+ }
+ h6->nexthdr = IPPROTO_TCP;
+ /* Copy the TCP header after the IPv6 one */
+ memcpy(h6 + 1,
+ skb->data + ETH_HLEN + sizeof(*h6) +
+ sizeof(struct hop_jumbo_hdr),
+ tcp_hdrlen(skb));
+ /* Leave ipv6 payload_len set to 0, as LSO v2 specs request. */
+ } else if (skb_vlan_tag_present(skb)) {
+ mlx5e_insert_vlan(start, skb, ihs);
+ ihs += VLAN_HLEN;
stats->added_vlan_packets++;
} else {
- eseg->inline_hdr.sz |= cpu_to_be16(attr->ihs);
- unsafe_memcpy(eseg->inline_hdr.start, skb->data, attr->ihs,
- /* This copy has been bounds-checked earlier in
- * mlx5i_sq_calc_wqe_attr() and intentionally
- * crosses a flex array boundary. Since it is
- * performance sensitive, splitting the copy is
- * undesirable.
- */);
+ unsafe_memcpy(eseg->inline_hdr.start, skb->data,
+ attr->ihs,
+ MLX5_UNSAFE_MEMCPY_DISCLAIMER);
}
+ eseg->inline_hdr.sz |= cpu_to_be16(ihs);
dseg += wqe_attr->ds_cnt_inl;
} else if (skb_vlan_tag_present(skb)) {
eseg->insert.type = cpu_to_be16(MLX5_ETH_WQE_INSERT_VLAN);
@@ -404,7 +447,7 @@ mlx5e_sq_xmit_wqe(struct mlx5e_txqsq *sq, struct sk_buff *skb,
}
dseg += wqe_attr->ds_cnt_ids;
- num_dma = mlx5e_txwqe_build_dsegs(sq, skb, skb->data + attr->ihs,
+ num_dma = mlx5e_txwqe_build_dsegs(sq, skb, skb->data + attr->ihs + attr->hopbyhop,
attr->headlen, dseg);
if (unlikely(num_dma < 0))
goto err_drop;
@@ -924,12 +967,34 @@ void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
eseg->mss = attr.mss;
if (attr.ihs) {
- memcpy(eseg->inline_hdr.start, skb->data, attr.ihs);
+ if (unlikely(attr.hopbyhop)) {
+ struct ipv6hdr *h6;
+
+ /* remove the HBH header.
+ * Layout: [Ethernet header][IPv6 header][HBH][TCP header]
+ */
+ unsafe_memcpy(eseg->inline_hdr.start, skb->data,
+ ETH_HLEN + sizeof(*h6),
+ MLX5_UNSAFE_MEMCPY_DISCLAIMER);
+ h6 = (struct ipv6hdr *)((char *)eseg->inline_hdr.start + ETH_HLEN);
+ h6->nexthdr = IPPROTO_TCP;
+ /* Copy the TCP header after the IPv6 one */
+ unsafe_memcpy(h6 + 1,
+ skb->data + ETH_HLEN + sizeof(*h6) +
+ sizeof(struct hop_jumbo_hdr),
+ tcp_hdrlen(skb),
+ MLX5_UNSAFE_MEMCPY_DISCLAIMER);
+ /* Leave ipv6 payload_len set to 0, as LSO v2 specs request. */
+ } else {
+ unsafe_memcpy(eseg->inline_hdr.start, skb->data,
+ attr.ihs,
+ MLX5_UNSAFE_MEMCPY_DISCLAIMER);
+ }
eseg->inline_hdr.sz = cpu_to_be16(attr.ihs);
dseg += wqe_attr.ds_cnt_inl;
}
- num_dma = mlx5e_txwqe_build_dsegs(sq, skb, skb->data + attr.ihs,
+ num_dma = mlx5e_txwqe_build_dsegs(sq, skb, skb->data + attr.ihs + attr.hopbyhop,
attr.headlen, dseg);
if (unlikely(num_dma < 0))
goto err_drop;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 3b151332e2f8..217cac29057f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -49,6 +49,7 @@
#include "en_tc.h"
#include "en/mapping.h"
#include "devlink.h"
+#include "lag/lag.h"
#define mlx5_esw_for_each_rep(esw, i, rep) \
xa_for_each(&((esw)->offloads.vport_reps), i, rep)
@@ -418,6 +419,8 @@ esw_setup_vport_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *f
dest[dest_idx].vport.vhca_id =
MLX5_CAP_GEN(esw_attr->dests[attr_idx].mdev, vhca_id);
dest[dest_idx].vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
+ if (mlx5_lag_mpesw_is_activated(esw->dev))
+ dest[dest_idx].type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
}
if (esw_attr->dests[attr_idx].flags & MLX5_ESW_DEST_ENCAP) {
if (pkt_reformat) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index fb8175672478..84caffe4c278 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -2673,28 +2673,6 @@ static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns)
clean_tree(&root_ns->ns.node);
}
-void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
-{
- struct mlx5_flow_steering *steering = dev->priv.steering;
-
- cleanup_root_ns(steering->root_ns);
- cleanup_root_ns(steering->fdb_root_ns);
- steering->fdb_root_ns = NULL;
- kfree(steering->fdb_sub_ns);
- steering->fdb_sub_ns = NULL;
- cleanup_root_ns(steering->port_sel_root_ns);
- cleanup_root_ns(steering->sniffer_rx_root_ns);
- cleanup_root_ns(steering->sniffer_tx_root_ns);
- cleanup_root_ns(steering->rdma_rx_root_ns);
- cleanup_root_ns(steering->rdma_tx_root_ns);
- cleanup_root_ns(steering->egress_root_ns);
- mlx5_cleanup_fc_stats(dev);
- kmem_cache_destroy(steering->ftes_cache);
- kmem_cache_destroy(steering->fgs_cache);
- mlx5_ft_pool_destroy(dev);
- kfree(steering);
-}
-
static int init_sniffer_tx_root_ns(struct mlx5_flow_steering *steering)
{
struct fs_prio *prio;
@@ -3096,42 +3074,27 @@ cleanup:
return err;
}
-int mlx5_init_fs(struct mlx5_core_dev *dev)
+void mlx5_fs_core_cleanup(struct mlx5_core_dev *dev)
{
- struct mlx5_flow_steering *steering;
- int err = 0;
-
- err = mlx5_init_fc_stats(dev);
- if (err)
- return err;
-
- err = mlx5_ft_pool_init(dev);
- if (err)
- return err;
-
- steering = kzalloc(sizeof(*steering), GFP_KERNEL);
- if (!steering) {
- err = -ENOMEM;
- goto err;
- }
-
- steering->dev = dev;
- dev->priv.steering = steering;
+ struct mlx5_flow_steering *steering = dev->priv.steering;
- if (mlx5_fs_dr_is_supported(dev))
- steering->mode = MLX5_FLOW_STEERING_MODE_SMFS;
- else
- steering->mode = MLX5_FLOW_STEERING_MODE_DMFS;
+ cleanup_root_ns(steering->root_ns);
+ cleanup_root_ns(steering->fdb_root_ns);
+ steering->fdb_root_ns = NULL;
+ kfree(steering->fdb_sub_ns);
+ steering->fdb_sub_ns = NULL;
+ cleanup_root_ns(steering->port_sel_root_ns);
+ cleanup_root_ns(steering->sniffer_rx_root_ns);
+ cleanup_root_ns(steering->sniffer_tx_root_ns);
+ cleanup_root_ns(steering->rdma_rx_root_ns);
+ cleanup_root_ns(steering->rdma_tx_root_ns);
+ cleanup_root_ns(steering->egress_root_ns);
+}
- steering->fgs_cache = kmem_cache_create("mlx5_fs_fgs",
- sizeof(struct mlx5_flow_group), 0,
- 0, NULL);
- steering->ftes_cache = kmem_cache_create("mlx5_fs_ftes", sizeof(struct fs_fte), 0,
- 0, NULL);
- if (!steering->ftes_cache || !steering->fgs_cache) {
- err = -ENOMEM;
- goto err;
- }
+int mlx5_fs_core_init(struct mlx5_core_dev *dev)
+{
+ struct mlx5_flow_steering *steering = dev->priv.steering;
+ int err = 0;
if ((((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&
(MLX5_CAP_GEN(dev, nic_flow_table))) ||
@@ -3189,8 +3152,64 @@ int mlx5_init_fs(struct mlx5_core_dev *dev)
}
return 0;
+
+err:
+ mlx5_fs_core_cleanup(dev);
+ return err;
+}
+
+void mlx5_fs_core_free(struct mlx5_core_dev *dev)
+{
+ struct mlx5_flow_steering *steering = dev->priv.steering;
+
+ kmem_cache_destroy(steering->ftes_cache);
+ kmem_cache_destroy(steering->fgs_cache);
+ kfree(steering);
+ mlx5_ft_pool_destroy(dev);
+ mlx5_cleanup_fc_stats(dev);
+}
+
+int mlx5_fs_core_alloc(struct mlx5_core_dev *dev)
+{
+ struct mlx5_flow_steering *steering;
+ int err = 0;
+
+ err = mlx5_init_fc_stats(dev);
+ if (err)
+ return err;
+
+ err = mlx5_ft_pool_init(dev);
+ if (err)
+ goto err;
+
+ steering = kzalloc(sizeof(*steering), GFP_KERNEL);
+ if (!steering) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ steering->dev = dev;
+ dev->priv.steering = steering;
+
+ if (mlx5_fs_dr_is_supported(dev))
+ steering->mode = MLX5_FLOW_STEERING_MODE_SMFS;
+ else
+ steering->mode = MLX5_FLOW_STEERING_MODE_DMFS;
+
+ steering->fgs_cache = kmem_cache_create("mlx5_fs_fgs",
+ sizeof(struct mlx5_flow_group), 0,
+ 0, NULL);
+ steering->ftes_cache = kmem_cache_create("mlx5_fs_ftes", sizeof(struct fs_fte), 0,
+ 0, NULL);
+ if (!steering->ftes_cache || !steering->fgs_cache) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ return 0;
+
err:
- mlx5_cleanup_fs(dev);
+ mlx5_fs_core_free(dev);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
index 67cad7a6d836..3af50fd04d28 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
@@ -299,8 +299,10 @@ int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns,
enum mlx5_flow_steering_mode mode);
-int mlx5_init_fs(struct mlx5_core_dev *dev);
-void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
+int mlx5_fs_core_alloc(struct mlx5_core_dev *dev);
+void mlx5_fs_core_free(struct mlx5_core_dev *dev);
+int mlx5_fs_core_init(struct mlx5_core_dev *dev);
+void mlx5_fs_core_cleanup(struct mlx5_core_dev *dev);
int mlx5_fs_egress_acls_init(struct mlx5_core_dev *dev, int total_vports);
void mlx5_fs_egress_acls_cleanup(struct mlx5_core_dev *dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
index 84df0d56a2b6..052af4901c0b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
@@ -8,7 +8,8 @@
enum {
MLX5_FW_RESET_FLAGS_RESET_REQUESTED,
MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST,
- MLX5_FW_RESET_FLAGS_PENDING_COMP
+ MLX5_FW_RESET_FLAGS_PENDING_COMP,
+ MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS
};
struct mlx5_fw_reset {
@@ -208,7 +209,10 @@ static void poll_sync_reset(struct timer_list *t)
if (fatal_error) {
mlx5_core_warn(dev, "Got Device Reset\n");
- queue_work(fw_reset->wq, &fw_reset->reset_reload_work);
+ if (!test_bit(MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, &fw_reset->reset_flags))
+ queue_work(fw_reset->wq, &fw_reset->reset_reload_work);
+ else
+ mlx5_core_err(dev, "Device is being removed, Drop new reset work\n");
return;
}
@@ -433,9 +437,12 @@ static int fw_reset_event_notifier(struct notifier_block *nb, unsigned long acti
struct mlx5_fw_reset *fw_reset = mlx5_nb_cof(nb, struct mlx5_fw_reset, nb);
struct mlx5_eqe *eqe = data;
+ if (test_bit(MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, &fw_reset->reset_flags))
+ return NOTIFY_DONE;
+
switch (eqe->sub_type) {
case MLX5_GENERAL_SUBTYPE_FW_LIVE_PATCH_EVENT:
- queue_work(fw_reset->wq, &fw_reset->fw_live_patch_work);
+ queue_work(fw_reset->wq, &fw_reset->fw_live_patch_work);
break;
case MLX5_GENERAL_SUBTYPE_PCI_SYNC_FOR_FW_UPDATE_EVENT:
mlx5_sync_reset_events_handle(fw_reset, eqe);
@@ -479,6 +486,18 @@ void mlx5_fw_reset_events_stop(struct mlx5_core_dev *dev)
mlx5_eq_notifier_unregister(dev, &dev->priv.fw_reset->nb);
}
+void mlx5_drain_fw_reset(struct mlx5_core_dev *dev)
+{
+ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
+
+ set_bit(MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, &fw_reset->reset_flags);
+ cancel_work_sync(&fw_reset->fw_live_patch_work);
+ cancel_work_sync(&fw_reset->reset_request_work);
+ cancel_work_sync(&fw_reset->reset_reload_work);
+ cancel_work_sync(&fw_reset->reset_now_work);
+ cancel_work_sync(&fw_reset->reset_abort_work);
+}
+
int mlx5_fw_reset_init(struct mlx5_core_dev *dev)
{
struct mlx5_fw_reset *fw_reset = kzalloc(sizeof(*fw_reset), GFP_KERNEL);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h
index 694fc7cb2684..dc141c7e641a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h
@@ -16,6 +16,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev);
int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev);
void mlx5_fw_reset_events_start(struct mlx5_core_dev *dev);
void mlx5_fw_reset_events_stop(struct mlx5_core_dev *dev);
+void mlx5_drain_fw_reset(struct mlx5_core_dev *dev);
int mlx5_fw_reset_init(struct mlx5_core_dev *dev);
void mlx5_fw_reset_cleanup(struct mlx5_core_dev *dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
index f4f7eaf16446..8da73ef5680f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
@@ -221,7 +221,6 @@ static int mlx5i_get_link_ksettings(struct net_device *netdev,
return 0;
}
-#ifdef CONFIG_MLX5_EN_RXNFC
static u32 mlx5i_flow_type_mask(u32 flow_type)
{
return flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
@@ -243,9 +242,18 @@ static int mlx5i_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
{
struct mlx5e_priv *priv = mlx5i_epriv(dev);
+ /* ETHTOOL_GRXRINGS is needed by ethtool -x which is not part
+ * of rxnfc. We keep this logic out of mlx5e_ethtool_get_rxnfc,
+ * to avoid breaking "ethtool -x" when mlx5e_ethtool_get_rxnfc
+ * is compiled out via CONFIG_MLX5_EN_RXNFC=n.
+ */
+ if (info->cmd == ETHTOOL_GRXRINGS) {
+ info->data = priv->channels.params.num_channels;
+ return 0;
+ }
+
return mlx5e_ethtool_get_rxnfc(priv, info, rule_locs);
}
-#endif
const struct ethtool_ops mlx5i_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
@@ -263,10 +271,8 @@ const struct ethtool_ops mlx5i_ethtool_ops = {
.get_coalesce = mlx5i_get_coalesce,
.set_coalesce = mlx5i_set_coalesce,
.get_ts_info = mlx5i_get_ts_info,
-#ifdef CONFIG_MLX5_EN_RXNFC
.get_rxnfc = mlx5i_get_rxnfc,
.set_rxnfc = mlx5i_set_rxnfc,
-#endif
.get_link_ksettings = mlx5i_get_link_ksettings,
.get_link = ethtool_op_get_link,
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c
index 443daf6e3d4b..15e41dc84d53 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c
@@ -5,12 +5,13 @@
static char *get_str_mode_type(struct mlx5_lag *ldev)
{
- if (ldev->flags & MLX5_LAG_FLAG_ROCE)
- return "roce";
- if (ldev->flags & MLX5_LAG_FLAG_SRIOV)
- return "switchdev";
- if (ldev->flags & MLX5_LAG_FLAG_MULTIPATH)
- return "multipath";
+ switch (ldev->mode) {
+ case MLX5_LAG_MODE_ROCE: return "roce";
+ case MLX5_LAG_MODE_SRIOV: return "switchdev";
+ case MLX5_LAG_MODE_MULTIPATH: return "multipath";
+ case MLX5_LAG_MODE_MPESW: return "multiport_eswitch";
+ default: return "invalid";
+ }
return NULL;
}
@@ -43,11 +44,11 @@ static int port_sel_mode_show(struct seq_file *file, void *priv)
ldev = dev->priv.lag;
mutex_lock(&ldev->lock);
if (__mlx5_lag_is_active(ldev))
- mode = get_str_port_sel_mode(ldev->flags);
+ mode = mlx5_get_str_port_sel_mode(ldev);
else
ret = -EINVAL;
mutex_unlock(&ldev->lock);
- if (ret || !mode)
+ if (ret)
return ret;
seq_printf(file, "%s\n", mode);
@@ -79,7 +80,7 @@ static int flags_show(struct seq_file *file, void *priv)
mutex_lock(&ldev->lock);
lag_active = __mlx5_lag_is_active(ldev);
if (lag_active)
- shared_fdb = ldev->shared_fdb;
+ shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
mutex_unlock(&ldev->lock);
if (!lag_active)
@@ -103,7 +104,7 @@ static int mapping_show(struct seq_file *file, void *priv)
mutex_lock(&ldev->lock);
lag_active = __mlx5_lag_is_active(ldev);
if (lag_active) {
- if (ldev->flags & MLX5_LAG_FLAG_HASH_BASED) {
+ if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags)) {
mlx5_infer_tx_enabled(&ldev->tracker, ldev->ports, ports,
&num_ports);
hash = true;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index b6dd9043061f..552b6e26e701 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -41,6 +41,7 @@
#include "esw/acl/ofld.h"
#include "lag.h"
#include "mp.h"
+#include "mpesw.h"
enum {
MLX5_LAG_EGRESS_PORT_1 = 1,
@@ -53,21 +54,33 @@ enum {
*/
static DEFINE_SPINLOCK(lag_lock);
-static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 *ports, bool shared_fdb, u8 flags)
+static int get_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags)
{
+ if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags))
+ return MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT;
+
+ if (mode == MLX5_LAG_MODE_MPESW)
+ return MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_MPESW;
+
+ return MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY;
+}
+
+static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 *ports, int mode,
+ unsigned long flags)
+{
+ bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
+ int port_sel_mode = get_port_sel_mode(mode, flags);
u32 in[MLX5_ST_SZ_DW(create_lag_in)] = {};
- void *lag_ctx = MLX5_ADDR_OF(create_lag_in, in, ctx);
+ void *lag_ctx;
+ lag_ctx = MLX5_ADDR_OF(create_lag_in, in, ctx);
MLX5_SET(create_lag_in, in, opcode, MLX5_CMD_OP_CREATE_LAG);
-
MLX5_SET(lagc, lag_ctx, fdb_selection_mode, shared_fdb);
- if (!(flags & MLX5_LAG_FLAG_HASH_BASED)) {
+ if (port_sel_mode == MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY) {
MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
- } else {
- MLX5_SET(lagc, lag_ctx, port_select_mode,
- MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT);
}
+ MLX5_SET(lagc, lag_ctx, port_select_mode, port_sel_mode);
return mlx5_cmd_exec_in(dev, create_lag, in);
}
@@ -139,7 +152,7 @@ void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
static void mlx5_lag_print_mapping(struct mlx5_core_dev *dev,
struct mlx5_lag *ldev,
struct lag_tracker *tracker,
- u8 flags)
+ unsigned long flags)
{
char buf[MLX5_MAX_PORTS * 10 + 1] = {};
u8 enabled_ports[MLX5_MAX_PORTS] = {};
@@ -150,7 +163,7 @@ static void mlx5_lag_print_mapping(struct mlx5_core_dev *dev,
int i;
int j;
- if (flags & MLX5_LAG_FLAG_HASH_BASED) {
+ if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) {
mlx5_infer_tx_enabled(tracker, ldev->ports, enabled_ports,
&num_enabled);
for (i = 0; i < num_enabled; i++) {
@@ -187,7 +200,8 @@ static void mlx5_ldev_free(struct kref *ref)
if (ldev->nb.notifier_call)
unregister_netdevice_notifier_net(&init_net, &ldev->nb);
mlx5_lag_mp_cleanup(ldev);
- cancel_delayed_work_sync(&ldev->bond_work);
+ mlx5_lag_mpesw_cleanup(ldev);
+ cancel_work_sync(&ldev->mpesw_work);
destroy_workqueue(ldev->wq);
mutex_destroy(&ldev->lock);
kfree(ldev);
@@ -227,11 +241,14 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(struct mlx5_core_dev *dev)
ldev->nb.notifier_call = NULL;
mlx5_core_err(dev, "Failed to register LAG netdev notifier\n");
}
+ ldev->mode = MLX5_LAG_MODE_NONE;
err = mlx5_lag_mp_init(ldev);
if (err)
mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",
err);
+
+ mlx5_lag_mpesw_init(ldev);
ldev->ports = MLX5_CAP_GEN(dev, num_lag_ports);
ldev->buckets = 1;
@@ -252,12 +269,12 @@ int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
static bool __mlx5_lag_is_roce(struct mlx5_lag *ldev)
{
- return !!(ldev->flags & MLX5_LAG_FLAG_ROCE);
+ return ldev->mode == MLX5_LAG_MODE_ROCE;
}
static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev)
{
- return !!(ldev->flags & MLX5_LAG_FLAG_SRIOV);
+ return ldev->mode == MLX5_LAG_MODE_SRIOV;
}
/* Create a mapping between steering slots and active ports.
@@ -372,7 +389,7 @@ static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- if (ldev->flags & MLX5_LAG_FLAG_HASH_BASED)
+ if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags))
return mlx5_lag_port_sel_modify(ldev, ports);
return mlx5_cmd_modify_lag(dev0, ldev->ports, ports);
}
@@ -404,19 +421,19 @@ void mlx5_modify_lag(struct mlx5_lag *ldev,
memcpy(ldev->v2p_map, ports, sizeof(ports));
mlx5_lag_print_mapping(dev0, ldev, tracker,
- ldev->flags);
+ ldev->mode_flags);
break;
}
}
if (tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP &&
- !(ldev->flags & MLX5_LAG_FLAG_ROCE))
+ !(ldev->mode == MLX5_LAG_MODE_ROCE))
mlx5_lag_drop_rule_setup(ldev, tracker);
}
#define MLX5_LAG_ROCE_HASH_PORTS_SUPPORTED 4
static int mlx5_lag_set_port_sel_mode_roce(struct mlx5_lag *ldev,
- struct lag_tracker *tracker, u8 *flags)
+ unsigned long *flags)
{
struct lag_func *dev0 = &ldev->pf[MLX5_LAG_P1];
@@ -424,7 +441,7 @@ static int mlx5_lag_set_port_sel_mode_roce(struct mlx5_lag *ldev,
/* Four ports are support only in hash mode */
if (!MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table))
return -EINVAL;
- *flags |= MLX5_LAG_FLAG_HASH_BASED;
+ set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags);
if (ldev->ports > 2)
ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS;
}
@@ -432,49 +449,67 @@ static int mlx5_lag_set_port_sel_mode_roce(struct mlx5_lag *ldev,
return 0;
}
-static int mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev,
- struct lag_tracker *tracker, u8 *flags)
+static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev,
+ struct lag_tracker *tracker,
+ enum mlx5_lag_mode mode,
+ unsigned long *flags)
{
struct lag_func *dev0 = &ldev->pf[MLX5_LAG_P1];
+ if (mode == MLX5_LAG_MODE_MPESW)
+ return;
+
if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) &&
tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH)
- *flags |= MLX5_LAG_FLAG_HASH_BASED;
-
- return 0;
+ set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags);
}
-static int mlx5_lag_set_port_sel_mode(struct mlx5_lag *ldev,
- struct lag_tracker *tracker, u8 *flags)
+static int mlx5_lag_set_flags(struct mlx5_lag *ldev, enum mlx5_lag_mode mode,
+ struct lag_tracker *tracker, bool shared_fdb,
+ unsigned long *flags)
{
- bool roce_lag = !!(*flags & MLX5_LAG_FLAG_ROCE);
+ bool roce_lag = mode == MLX5_LAG_MODE_ROCE;
+
+ *flags = 0;
+ if (shared_fdb)
+ set_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, flags);
if (roce_lag)
- return mlx5_lag_set_port_sel_mode_roce(ldev, tracker, flags);
- return mlx5_lag_set_port_sel_mode_offloads(ldev, tracker, flags);
+ return mlx5_lag_set_port_sel_mode_roce(ldev, flags);
+
+ mlx5_lag_set_port_sel_mode_offloads(ldev, tracker, mode, flags);
+ return 0;
}
-char *get_str_port_sel_mode(u8 flags)
+char *mlx5_get_str_port_sel_mode(struct mlx5_lag *ldev)
{
- if (flags & MLX5_LAG_FLAG_HASH_BASED)
- return "hash";
- return "queue_affinity";
+ int port_sel_mode = get_port_sel_mode(ldev->mode, ldev->mode_flags);
+
+ switch (port_sel_mode) {
+ case MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY: return "queue_affinity";
+ case MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT: return "hash";
+ case MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_MPESW: return "mpesw";
+ default: return "invalid";
+ }
}
static int mlx5_create_lag(struct mlx5_lag *ldev,
struct lag_tracker *tracker,
- bool shared_fdb, u8 flags)
+ enum mlx5_lag_mode mode,
+ unsigned long flags)
{
+ bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
int err;
- mlx5_lag_print_mapping(dev0, ldev, tracker, flags);
+ if (tracker)
+ mlx5_lag_print_mapping(dev0, ldev, tracker, flags);
mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n",
- shared_fdb, get_str_port_sel_mode(flags));
+ shared_fdb, mlx5_get_str_port_sel_mode(ldev));
- err = mlx5_cmd_create_lag(dev0, ldev->v2p_map, shared_fdb, flags);
+ err = mlx5_cmd_create_lag(dev0, ldev->v2p_map, mode, flags);
if (err) {
mlx5_core_err(dev0,
"Failed to create LAG (%d)\n",
@@ -503,33 +538,35 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
int mlx5_activate_lag(struct mlx5_lag *ldev,
struct lag_tracker *tracker,
- u8 flags,
+ enum mlx5_lag_mode mode,
bool shared_fdb)
{
- bool roce_lag = !!(flags & MLX5_LAG_FLAG_ROCE);
+ bool roce_lag = mode == MLX5_LAG_MODE_ROCE;
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+ unsigned long flags = 0;
int err;
- err = mlx5_lag_set_port_sel_mode(ldev, tracker, &flags);
+ err = mlx5_lag_set_flags(ldev, mode, tracker, shared_fdb, &flags);
if (err)
return err;
- mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ldev->v2p_map);
-
- if (flags & MLX5_LAG_FLAG_HASH_BASED) {
- err = mlx5_lag_port_sel_create(ldev, tracker->hash_type,
- ldev->v2p_map);
- if (err) {
- mlx5_core_err(dev0,
- "Failed to create LAG port selection(%d)\n",
- err);
- return err;
+ if (mode != MLX5_LAG_MODE_MPESW) {
+ mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ldev->v2p_map);
+ if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) {
+ err = mlx5_lag_port_sel_create(ldev, tracker->hash_type,
+ ldev->v2p_map);
+ if (err) {
+ mlx5_core_err(dev0,
+ "Failed to create LAG port selection(%d)\n",
+ err);
+ return err;
+ }
}
}
- err = mlx5_create_lag(ldev, tracker, shared_fdb, flags);
+ err = mlx5_create_lag(ldev, tracker, mode, flags);
if (err) {
- if (flags & MLX5_LAG_FLAG_HASH_BASED)
+ if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags))
mlx5_lag_port_sel_destroy(ldev);
if (roce_lag)
mlx5_core_err(dev0,
@@ -541,12 +578,12 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
return err;
}
- if (tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP &&
+ if (tracker && tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP &&
!roce_lag)
mlx5_lag_drop_rule_setup(ldev, tracker);
- ldev->flags |= flags;
- ldev->shared_fdb = shared_fdb;
+ ldev->mode = mode;
+ ldev->mode_flags = flags;
return 0;
}
@@ -556,16 +593,17 @@ static int mlx5_deactivate_lag(struct mlx5_lag *ldev)
struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
bool roce_lag = __mlx5_lag_is_roce(ldev);
- u8 flags = ldev->flags;
+ unsigned long flags = ldev->mode_flags;
int err;
- ldev->flags &= ~MLX5_LAG_MODE_FLAGS;
+ ldev->mode = MLX5_LAG_MODE_NONE;
+ ldev->mode_flags = 0;
mlx5_lag_mp_reset(ldev);
- if (ldev->shared_fdb) {
+ if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) {
mlx5_eswitch_offloads_destroy_single_fdb(dev0->priv.eswitch,
dev1->priv.eswitch);
- ldev->shared_fdb = false;
+ clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
}
MLX5_SET(destroy_lag_in, in, opcode, MLX5_CMD_OP_DESTROY_LAG);
@@ -582,7 +620,7 @@ static int mlx5_deactivate_lag(struct mlx5_lag *ldev)
return err;
}
- if (flags & MLX5_LAG_FLAG_HASH_BASED)
+ if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags))
mlx5_lag_port_sel_destroy(ldev);
if (mlx5_lag_has_drop_rule(ldev))
mlx5_lag_drop_rule_cleanup(ldev);
@@ -656,11 +694,11 @@ static void mlx5_lag_remove_devices(struct mlx5_lag *ldev)
}
}
-static void mlx5_disable_lag(struct mlx5_lag *ldev)
+void mlx5_disable_lag(struct mlx5_lag *ldev)
{
+ bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
- bool shared_fdb = ldev->shared_fdb;
bool roce_lag;
int err;
int i;
@@ -693,7 +731,7 @@ static void mlx5_disable_lag(struct mlx5_lag *ldev)
}
}
-static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
+bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
@@ -729,6 +767,18 @@ static bool mlx5_lag_is_roce_lag(struct mlx5_lag *ldev)
return roce_lag;
}
+static bool mlx5_lag_should_modify_lag(struct mlx5_lag *ldev, bool do_bond)
+{
+ return do_bond && __mlx5_lag_is_active(ldev) &&
+ ldev->mode != MLX5_LAG_MODE_MPESW;
+}
+
+static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond)
+{
+ return !do_bond && __mlx5_lag_is_active(ldev) &&
+ ldev->mode != MLX5_LAG_MODE_MPESW;
+}
+
static void mlx5_do_bond(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
@@ -759,8 +809,8 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
mlx5_lag_remove_devices(ldev);
err = mlx5_activate_lag(ldev, &tracker,
- roce_lag ? MLX5_LAG_FLAG_ROCE :
- MLX5_LAG_FLAG_SRIOV,
+ roce_lag ? MLX5_LAG_MODE_ROCE :
+ MLX5_LAG_MODE_SRIOV,
shared_fdb);
if (err) {
if (shared_fdb || roce_lag)
@@ -791,9 +841,9 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
return;
}
}
- } else if (do_bond && __mlx5_lag_is_active(ldev)) {
+ } else if (mlx5_lag_should_modify_lag(ldev, do_bond)) {
mlx5_modify_lag(ldev, &tracker);
- } else if (!do_bond && __mlx5_lag_is_active(ldev)) {
+ } else if (mlx5_lag_should_disable_lag(ldev, do_bond)) {
mlx5_disable_lag(ldev);
}
}
@@ -831,7 +881,6 @@ static void mlx5_do_bond_work(struct work_struct *work)
static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev,
struct lag_tracker *tracker,
- struct net_device *ndev,
struct netdev_notifier_changeupper_info *info)
{
struct net_device *upper = info->upper_dev, *ndev_tmp;
@@ -968,6 +1017,7 @@ static int mlx5_handle_changeinfodata_event(struct mlx5_lag *ldev,
return 1;
}
+/* this handler is always registered to netdev events */
static int mlx5_lag_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
@@ -987,8 +1037,7 @@ static int mlx5_lag_netdev_event(struct notifier_block *this,
switch (event) {
case NETDEV_CHANGEUPPER:
- changed = mlx5_handle_changeupper_event(ldev, &tracker, ndev,
- ptr);
+ changed = mlx5_handle_changeupper_event(ldev, &tracker, ptr);
break;
case NETDEV_CHANGELOWERSTATE:
changed = mlx5_handle_changelowerstate_event(ldev, &tracker,
@@ -1156,7 +1205,7 @@ void mlx5_lag_remove_netdev(struct mlx5_core_dev *dev,
mutex_lock(&ldev->lock);
mlx5_ldev_remove_netdev(ldev, netdev);
- ldev->flags &= ~MLX5_LAG_FLAG_READY;
+ clear_bit(MLX5_LAG_FLAG_NDEVS_READY, &ldev->state_flags);
lag_is_active = __mlx5_lag_is_active(ldev);
mutex_unlock(&ldev->lock);
@@ -1183,7 +1232,7 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
break;
if (i >= ldev->ports)
- ldev->flags |= MLX5_LAG_FLAG_READY;
+ set_bit(MLX5_LAG_FLAG_NDEVS_READY, &ldev->state_flags);
mutex_unlock(&ldev->lock);
mlx5_queue_bond_work(ldev, 0);
}
@@ -1252,7 +1301,8 @@ bool mlx5_lag_is_shared_fdb(struct mlx5_core_dev *dev)
spin_lock(&lag_lock);
ldev = mlx5_lag_dev(dev);
- res = ldev && __mlx5_lag_is_sriov(ldev) && ldev->shared_fdb;
+ res = ldev && __mlx5_lag_is_sriov(ldev) &&
+ test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
spin_unlock(&lag_lock);
return res;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
index 46683b84ff84..72f70fad4641 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
@@ -10,6 +10,7 @@
#include "mlx5_core.h"
#include "mp.h"
#include "port_sel.h"
+#include "mpesw.h"
enum {
MLX5_LAG_P1,
@@ -17,16 +18,21 @@ enum {
};
enum {
- MLX5_LAG_FLAG_ROCE = 1 << 0,
- MLX5_LAG_FLAG_SRIOV = 1 << 1,
- MLX5_LAG_FLAG_MULTIPATH = 1 << 2,
- MLX5_LAG_FLAG_READY = 1 << 3,
- MLX5_LAG_FLAG_HASH_BASED = 1 << 4,
+ MLX5_LAG_FLAG_NDEVS_READY,
};
-#define MLX5_LAG_MODE_FLAGS (MLX5_LAG_FLAG_ROCE | MLX5_LAG_FLAG_SRIOV |\
- MLX5_LAG_FLAG_MULTIPATH | \
- MLX5_LAG_FLAG_HASH_BASED)
+enum {
+ MLX5_LAG_MODE_FLAG_HASH_BASED,
+ MLX5_LAG_MODE_FLAG_SHARED_FDB,
+};
+
+enum mlx5_lag_mode {
+ MLX5_LAG_MODE_NONE,
+ MLX5_LAG_MODE_ROCE,
+ MLX5_LAG_MODE_SRIOV,
+ MLX5_LAG_MODE_MULTIPATH,
+ MLX5_LAG_MODE_MPESW,
+};
struct lag_func {
struct mlx5_core_dev *dev;
@@ -47,22 +53,25 @@ struct lag_tracker {
* It serves both its phys functions.
*/
struct mlx5_lag {
- u8 flags;
+ enum mlx5_lag_mode mode;
+ unsigned long mode_flags;
+ unsigned long state_flags;
u8 ports;
u8 buckets;
int mode_changes_in_progress;
- bool shared_fdb;
u8 v2p_map[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS];
struct kref ref;
struct lag_func pf[MLX5_MAX_PORTS];
struct lag_tracker tracker;
struct workqueue_struct *wq;
struct delayed_work bond_work;
+ struct work_struct mpesw_work;
struct notifier_block nb;
struct lag_mp lag_mp;
struct mlx5_lag_port_sel port_sel;
/* Protect lag fields/state changes */
struct mutex lock;
+ struct lag_mpesw lag_mpesw;
};
static inline struct mlx5_lag *
@@ -74,29 +83,33 @@ mlx5_lag_dev(struct mlx5_core_dev *dev)
static inline bool
__mlx5_lag_is_active(struct mlx5_lag *ldev)
{
- return !!(ldev->flags & MLX5_LAG_MODE_FLAGS);
+ return ldev->mode != MLX5_LAG_MODE_NONE;
}
static inline bool
mlx5_lag_is_ready(struct mlx5_lag *ldev)
{
- return ldev->flags & MLX5_LAG_FLAG_READY;
+ return test_bit(MLX5_LAG_FLAG_NDEVS_READY, &ldev->state_flags);
}
void mlx5_modify_lag(struct mlx5_lag *ldev,
struct lag_tracker *tracker);
int mlx5_activate_lag(struct mlx5_lag *ldev,
struct lag_tracker *tracker,
- u8 flags,
+ enum mlx5_lag_mode mode,
bool shared_fdb);
int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
struct net_device *ndev);
+bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev);
+void mlx5_lag_del_mpesw_rule(struct mlx5_core_dev *dev);
+int mlx5_lag_add_mpesw_rule(struct mlx5_core_dev *dev);
-char *get_str_port_sel_mode(u8 flags);
+char *mlx5_get_str_port_sel_mode(struct mlx5_lag *ldev);
void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
u8 *ports, int *num_enabled);
void mlx5_ldev_add_debugfs(struct mlx5_core_dev *dev);
void mlx5_ldev_remove_debugfs(struct dentry *dbg);
+void mlx5_disable_lag(struct mlx5_lag *ldev);
#endif /* __MLX5_LAG_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
index d6c3e6dfd71f..0259a149a64c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
@@ -11,7 +11,7 @@
static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev)
{
- return !!(ldev->flags & MLX5_LAG_FLAG_MULTIPATH);
+ return ldev->mode == MLX5_LAG_MODE_MULTIPATH;
}
static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
@@ -179,7 +179,7 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
struct lag_tracker tracker;
tracker = ldev->tracker;
- mlx5_activate_lag(ldev, &tracker, MLX5_LAG_FLAG_MULTIPATH, false);
+ mlx5_activate_lag(ldev, &tracker, MLX5_LAG_MODE_MULTIPATH, false);
}
mlx5_lag_set_port_affinity(ldev, MLX5_LAG_NORMAL_AFFINITY);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
new file mode 100644
index 000000000000..ee4b25a50315
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include <linux/netdevice.h>
+#include <net/nexthop.h>
+#include "lag/lag.h"
+#include "eswitch.h"
+#include "lib/mlx5.h"
+
+void mlx5_mpesw_work(struct work_struct *work)
+{
+ struct mlx5_lag *ldev = container_of(work, struct mlx5_lag, mpesw_work);
+
+ mutex_lock(&ldev->lock);
+ mlx5_disable_lag(ldev);
+ mutex_unlock(&ldev->lock);
+}
+
+static void mlx5_lag_disable_mpesw(struct mlx5_core_dev *dev)
+{
+ struct mlx5_lag *ldev = dev->priv.lag;
+
+ if (!queue_work(ldev->wq, &ldev->mpesw_work))
+ mlx5_core_warn(dev, "failed to queue work\n");
+}
+
+void mlx5_lag_del_mpesw_rule(struct mlx5_core_dev *dev)
+{
+ struct mlx5_lag *ldev = dev->priv.lag;
+
+ if (!ldev)
+ return;
+
+ mutex_lock(&ldev->lock);
+ if (!atomic_dec_return(&ldev->lag_mpesw.mpesw_rule_count) &&
+ ldev->mode == MLX5_LAG_MODE_MPESW)
+ mlx5_lag_disable_mpesw(dev);
+ mutex_unlock(&ldev->lock);
+}
+
+int mlx5_lag_add_mpesw_rule(struct mlx5_core_dev *dev)
+{
+ struct mlx5_lag *ldev = dev->priv.lag;
+ bool shared_fdb;
+ int err = 0;
+
+ if (!ldev)
+ return 0;
+
+ mutex_lock(&ldev->lock);
+ if (atomic_add_return(1, &ldev->lag_mpesw.mpesw_rule_count) != 1)
+ goto out;
+
+ if (ldev->mode != MLX5_LAG_MODE_NONE) {
+ err = -EINVAL;
+ goto out;
+ }
+ shared_fdb = mlx5_shared_fdb_supported(ldev);
+ err = mlx5_activate_lag(ldev, NULL, MLX5_LAG_MODE_MPESW, shared_fdb);
+ if (err)
+ mlx5_core_warn(dev, "Failed to create LAG in MPESW mode (%d)\n", err);
+
+out:
+ mutex_unlock(&ldev->lock);
+ return err;
+}
+
+int mlx5_lag_do_mirred(struct mlx5_core_dev *mdev, struct net_device *out_dev)
+{
+ struct mlx5_lag *ldev = mdev->priv.lag;
+
+ if (!netif_is_bond_master(out_dev) || !ldev)
+ return 0;
+
+ mutex_lock(&ldev->lock);
+ if (ldev->mode == MLX5_LAG_MODE_MPESW) {
+ mutex_unlock(&ldev->lock);
+ return -EOPNOTSUPP;
+ }
+ mutex_unlock(&ldev->lock);
+ return 0;
+}
+
+bool mlx5_lag_mpesw_is_activated(struct mlx5_core_dev *dev)
+{
+ bool ret;
+
+ ret = dev->priv.lag && dev->priv.lag->mode == MLX5_LAG_MODE_MPESW;
+ return ret;
+}
+
+void mlx5_lag_mpesw_init(struct mlx5_lag *ldev)
+{
+ INIT_WORK(&ldev->mpesw_work, mlx5_mpesw_work);
+ atomic_set(&ldev->lag_mpesw.mpesw_rule_count, 0);
+}
+
+void mlx5_lag_mpesw_cleanup(struct mlx5_lag *ldev)
+{
+ cancel_delayed_work_sync(&ldev->bond_work);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h
new file mode 100644
index 000000000000..be4abcb8fcd5
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#ifndef __MLX5_LAG_MPESW_H__
+#define __MLX5_LAG_MPESW_H__
+
+#include "lag.h"
+#include "mlx5_core.h"
+
+struct lag_mpesw {
+ struct work_struct mpesw_work;
+ atomic_t mpesw_rule_count;
+};
+
+void mlx5_mpesw_work(struct work_struct *work);
+int mlx5_lag_do_mirred(struct mlx5_core_dev *mdev, struct net_device *out_dev);
+bool mlx5_lag_mpesw_is_activated(struct mlx5_core_dev *dev);
+#if IS_ENABLED(CONFIG_MLX5_ESWITCH)
+void mlx5_lag_mpesw_init(struct mlx5_lag *ldev);
+void mlx5_lag_mpesw_cleanup(struct mlx5_lag *ldev);
+#else
+static inline void mlx5_lag_mpesw_init(struct mlx5_lag *ldev) {}
+static inline void mlx5_lag_mpesw_cleanup(struct mlx5_lag *ldev) {}
+#endif
+
+#endif /* __MLX5_LAG_MPESW_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 84f75aa25214..fbd4dd76a19f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -936,6 +936,12 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
goto err_sf_table_cleanup;
}
+ err = mlx5_fs_core_alloc(dev);
+ if (err) {
+ mlx5_core_err(dev, "Failed to alloc flow steering\n");
+ goto err_fs;
+ }
+
dev->dm = mlx5_dm_create(dev);
if (IS_ERR(dev->dm))
mlx5_core_warn(dev, "Failed to init device memory%d\n", err);
@@ -946,6 +952,8 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
return 0;
+err_fs:
+ mlx5_sf_table_cleanup(dev);
err_sf_table_cleanup:
mlx5_sf_hw_table_cleanup(dev);
err_sf_hw_table_cleanup:
@@ -983,6 +991,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
mlx5_hv_vhca_destroy(dev->hv_vhca);
mlx5_fw_tracer_destroy(dev->tracer);
mlx5_dm_cleanup(dev);
+ mlx5_fs_core_free(dev);
mlx5_sf_table_cleanup(dev);
mlx5_sf_hw_table_cleanup(dev);
mlx5_vhca_event_cleanup(dev);
@@ -1181,7 +1190,7 @@ static int mlx5_load(struct mlx5_core_dev *dev)
goto err_fpga_start;
}
- err = mlx5_init_fs(dev);
+ err = mlx5_fs_core_init(dev);
if (err) {
mlx5_core_err(dev, "Failed to init flow steering\n");
goto err_fs;
@@ -1226,7 +1235,7 @@ err_ec:
err_vhca:
mlx5_vhca_event_stop(dev);
err_set_hca:
- mlx5_cleanup_fs(dev);
+ mlx5_fs_core_cleanup(dev);
err_fs:
mlx5_fpga_device_stop(dev);
err_fpga_start:
@@ -1252,7 +1261,7 @@ static void mlx5_unload(struct mlx5_core_dev *dev)
mlx5_ec_cleanup(dev);
mlx5_sf_hw_table_destroy(dev);
mlx5_vhca_event_stop(dev);
- mlx5_cleanup_fs(dev);
+ mlx5_fs_core_cleanup(dev);
mlx5_fpga_device_stop(dev);
mlx5_rsc_dump_cleanup(dev);
mlx5_hv_vhca_cleanup(dev->hv_vhca);
@@ -1608,6 +1617,10 @@ static void remove_one(struct pci_dev *pdev)
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
struct devlink *devlink = priv_to_devlink(dev);
+ /* mlx5_drain_fw_reset() is using devlink APIs. Hence, we must drain
+ * fw_reset before unregistering the devlink.
+ */
+ mlx5_drain_fw_reset(dev);
set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
devlink_unregister(devlink);
mlx5_sriov_disable(pdev);
@@ -1886,7 +1899,6 @@ static struct pci_driver mlx5_core_driver = {
* Return: Pointer to the associated mlx5_core_dev or NULL.
*/
struct mlx5_core_dev *mlx5_vf_get_core_dev(struct pci_dev *pdev)
- __acquires(&mdev->intf_state_mutex)
{
struct mlx5_core_dev *mdev;
@@ -1912,7 +1924,6 @@ EXPORT_SYMBOL(mlx5_vf_get_core_dev);
* access the mdev any more.
*/
void mlx5_vf_put_core_dev(struct mlx5_core_dev *mdev)
- __releases(&mdev->intf_state_mutex)
{
mutex_unlock(&mdev->intf_state_mutex);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
index db77f1d2eeb4..662f1d55e30e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
@@ -94,8 +94,8 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
if (msix_vec_count > max_msix)
return -EOVERFLOW;
- query_cap = kzalloc(query_sz, GFP_KERNEL);
- hca_cap = kzalloc(set_sz, GFP_KERNEL);
+ query_cap = kvzalloc(query_sz, GFP_KERNEL);
+ hca_cap = kvzalloc(set_sz, GFP_KERNEL);
if (!hca_cap || !query_cap) {
ret = -ENOMEM;
goto out;
@@ -118,8 +118,8 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1);
ret = mlx5_cmd_exec_in(dev, set_hca_cap, hca_cap);
out:
- kfree(hca_cap);
- kfree(query_cap);
+ kvfree(hca_cap);
+ kvfree(query_cap);
return ret;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
index 850937cd8bf9..1383550f44c1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
@@ -530,6 +530,37 @@ static int dr_action_handle_cs_recalc(struct mlx5dr_domain *dmn,
return 0;
}
+static void dr_action_modify_ttl_adjust(struct mlx5dr_domain *dmn,
+ struct mlx5dr_ste_actions_attr *attr,
+ bool rx_rule,
+ bool *recalc_cs_required)
+{
+ *recalc_cs_required = false;
+
+ /* if device supports csum recalculation - no adjustment needed */
+ if (mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps))
+ return;
+
+ /* no adjustment needed on TX rules */
+ if (!rx_rule)
+ return;
+
+ if (!MLX5_CAP_ESW_FLOWTABLE(dmn->mdev, fdb_ipv4_ttl_modify)) {
+ /* Ignore the modify TTL action.
+ * It is always kept as last HW action.
+ */
+ attr->modify_actions--;
+ return;
+ }
+
+ if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB)
+ /* Due to a HW bug on some devices, modifying TTL on RX flows
+ * will cause an incorrect checksum calculation. In such cases
+ * we will use a FW table to recalculate the checksum.
+ */
+ *recalc_cs_required = true;
+}
+
static void dr_action_print_sequence(struct mlx5dr_domain *dmn,
struct mlx5dr_action *actions[],
int last_idx)
@@ -650,8 +681,9 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
case DR_ACTION_TYP_MODIFY_HDR:
attr.modify_index = action->rewrite->index;
attr.modify_actions = action->rewrite->num_of_actions;
- recalc_cs_required = action->rewrite->modify_ttl &&
- !mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps);
+ if (action->rewrite->modify_ttl)
+ dr_action_modify_ttl_adjust(dmn, &attr, rx_rule,
+ &recalc_cs_required);
break;
case DR_ACTION_TYP_L2_TO_TNL_L2:
case DR_ACTION_TYP_L2_TO_TNL_L3:
@@ -732,12 +764,7 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
*new_hw_ste_arr_sz = nic_matcher->num_of_builders;
last_ste = ste_arr + DR_STE_SIZE * (nic_matcher->num_of_builders - 1);
- /* Due to a HW bug in some devices, modifying TTL on RX flows will
- * cause an incorrect checksum calculation. In this case we will
- * use a FW table to recalculate.
- */
- if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB &&
- rx_rule && recalc_cs_required && dest_action) {
+ if (recalc_cs_required && dest_action) {
ret = dr_action_handle_cs_recalc(dmn, dest_action, &attr.final_icm_addr);
if (ret) {
mlx5dr_err(dmn,
@@ -842,7 +869,8 @@ struct mlx5dr_action *
mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
struct mlx5dr_action_dest *dests,
u32 num_of_dests,
- bool ignore_flow_level)
+ bool ignore_flow_level,
+ u32 flow_source)
{
struct mlx5dr_cmd_flow_destination_hw_info *hw_dests;
struct mlx5dr_action **ref_actions;
@@ -914,7 +942,8 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
reformat_req,
&action->dest_tbl->fw_tbl.id,
&action->dest_tbl->fw_tbl.group_id,
- ignore_flow_level);
+ ignore_flow_level,
+ flow_source);
if (ret)
goto free_action;
@@ -1556,12 +1585,6 @@ dr_action_modify_check_is_ttl_modify(const void *sw_action)
return sw_field == MLX5_ACTION_IN_FIELD_OUT_IP_TTL;
}
-static bool dr_action_modify_ttl_ignore(struct mlx5dr_domain *dmn)
-{
- return !mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps) &&
- !MLX5_CAP_ESW_FLOWTABLE(dmn->mdev, fdb_ipv4_ttl_modify);
-}
-
static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
u32 max_hw_actions,
u32 num_sw_actions,
@@ -1573,6 +1596,7 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
const struct mlx5dr_ste_action_modify_field *hw_dst_action_info;
const struct mlx5dr_ste_action_modify_field *hw_src_action_info;
struct mlx5dr_domain *dmn = action->rewrite->dmn;
+ __be64 *modify_ttl_sw_action = NULL;
int ret, i, hw_idx = 0;
__be64 *sw_action;
__be64 hw_action;
@@ -1585,8 +1609,14 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
action->rewrite->allow_rx = 1;
action->rewrite->allow_tx = 1;
- for (i = 0; i < num_sw_actions; i++) {
- sw_action = &sw_actions[i];
+ for (i = 0; i < num_sw_actions || modify_ttl_sw_action; i++) {
+ /* modify TTL is handled separately, as a last action */
+ if (i == num_sw_actions) {
+ sw_action = modify_ttl_sw_action;
+ modify_ttl_sw_action = NULL;
+ } else {
+ sw_action = &sw_actions[i];
+ }
ret = dr_action_modify_check_field_limitation(action,
sw_action);
@@ -1595,10 +1625,9 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
if (!(*modify_ttl) &&
dr_action_modify_check_is_ttl_modify(sw_action)) {
- if (dr_action_modify_ttl_ignore(dmn))
- continue;
-
+ modify_ttl_sw_action = sw_action;
*modify_ttl = true;
+ continue;
}
/* Convert SW action to HW action */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c
index 68a4c32d5f34..f05ef0cd54ba 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_fw.c
@@ -104,7 +104,8 @@ int mlx5dr_fw_create_md_tbl(struct mlx5dr_domain *dmn,
bool reformat_req,
u32 *tbl_id,
u32 *group_id,
- bool ignore_flow_level)
+ bool ignore_flow_level,
+ u32 flow_source)
{
struct mlx5dr_cmd_create_flow_table_attr ft_attr = {};
struct mlx5dr_cmd_fte_info fte_info = {};
@@ -139,6 +140,7 @@ int mlx5dr_fw_create_md_tbl(struct mlx5dr_domain *dmn,
fte_info.val = val;
fte_info.dest_arr = dest;
fte_info.ignore_flow_level = ignore_flow_level;
+ fte_info.flow_context.flow_source = flow_source;
ret = mlx5dr_cmd_set_fte(dmn->mdev, 0, 0, &ft_info, *group_id, &fte_info);
if (ret) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
index 5a322335f204..2010d4ac6519 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
@@ -420,7 +420,7 @@ dr_ste_v0_set_actions_tx(struct mlx5dr_domain *dmn,
* encapsulation. The reason for that is that we support
* modify headers for outer headers only
*/
- if (action_type_set[DR_ACTION_TYP_MODIFY_HDR]) {
+ if (action_type_set[DR_ACTION_TYP_MODIFY_HDR] && attr->modify_actions) {
dr_ste_v0_set_entry_type(last_ste, DR_STE_TYPE_MODIFY_PKT);
dr_ste_v0_set_rewrite_actions(last_ste,
attr->modify_actions,
@@ -513,7 +513,7 @@ dr_ste_v0_set_actions_rx(struct mlx5dr_domain *dmn,
}
}
- if (action_type_set[DR_ACTION_TYP_MODIFY_HDR]) {
+ if (action_type_set[DR_ACTION_TYP_MODIFY_HDR] && attr->modify_actions) {
if (dr_ste_v0_get_entry_type(last_ste) == DR_STE_TYPE_MODIFY_PKT)
dr_ste_v0_arr_init_next(&last_ste,
added_stes,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
index 46866a5fc5ca..98320e3945ad 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
@@ -1461,7 +1461,8 @@ int mlx5dr_fw_create_md_tbl(struct mlx5dr_domain *dmn,
bool reformat_req,
u32 *tbl_id,
u32 *group_id,
- bool ignore_flow_level);
+ bool ignore_flow_level,
+ u32 flow_source);
void mlx5dr_fw_destroy_md_tbl(struct mlx5dr_domain *dmn, u32 tbl_id,
u32 group_id);
#endif /* _DR_TYPES_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
index 045b0cf90063..728f81882589 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
@@ -520,6 +520,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
} else if (num_term_actions > 1) {
bool ignore_flow_level =
!!(fte->action.flags & FLOW_ACT_IGNORE_FLOW_LEVEL);
+ u32 flow_source = fte->flow_context.flow_source;
if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX ||
fs_dr_num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) {
@@ -529,7 +530,8 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
tmp_action = mlx5dr_action_create_mult_dest_tbl(domain,
term_actions,
num_term_actions,
- ignore_flow_level);
+ ignore_flow_level,
+ flow_source);
if (!tmp_action) {
err = -EOPNOTSUPP;
goto free_actions;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
index ec5cbec0d455..7626c85643b1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
@@ -99,7 +99,8 @@ struct mlx5dr_action *
mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
struct mlx5dr_action_dest *dests,
u32 num_of_dests,
- bool ignore_flow_level);
+ bool ignore_flow_level,
+ u32 flow_source);
struct mlx5dr_action *mlx5dr_action_create_drop(void);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
index 8846d30a380a..ac020cb78072 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
@@ -280,7 +280,7 @@ int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
out_sz = MLX5_ST_SZ_BYTES(query_nic_vport_context_in) +
req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
- out = kzalloc(out_sz, GFP_KERNEL);
+ out = kvzalloc(out_sz, GFP_KERNEL);
if (!out)
return -ENOMEM;
@@ -307,7 +307,7 @@ int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
ether_addr_copy(addr_list[i], mac_addr);
}
out:
- kfree(out);
+ kvfree(out);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_mac_list);
@@ -335,7 +335,7 @@ int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
in_sz = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in) +
list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
- in = kzalloc(in_sz, GFP_KERNEL);
+ in = kvzalloc(in_sz, GFP_KERNEL);
if (!in)
return -ENOMEM;
@@ -360,7 +360,7 @@ int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
}
err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
- kfree(in);
+ kvfree(in);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list);
@@ -386,7 +386,7 @@ int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
list_size * MLX5_ST_SZ_BYTES(vlan_layout);
memset(out, 0, sizeof(out));
- in = kzalloc(in_sz, GFP_KERNEL);
+ in = kvzalloc(in_sz, GFP_KERNEL);
if (!in)
return -ENOMEM;
@@ -411,7 +411,7 @@ int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev,
}
err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
- kfree(in);
+ kvfree(in);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_vlans);
@@ -542,8 +542,8 @@ int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport,
out_sz += nout * sizeof(*gid);
- in = kzalloc(in_sz, GFP_KERNEL);
- out = kzalloc(out_sz, GFP_KERNEL);
+ in = kvzalloc(in_sz, GFP_KERNEL);
+ out = kvzalloc(out_sz, GFP_KERNEL);
if (!in || !out) {
err = -ENOMEM;
goto out;
@@ -573,8 +573,8 @@ int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport,
gid->global.interface_id = tmp->global.interface_id;
out:
- kfree(in);
- kfree(out);
+ kvfree(in);
+ kvfree(out);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_gid);
@@ -607,8 +607,8 @@ int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport,
out_sz += nout * MLX5_ST_SZ_BYTES(pkey);
- in = kzalloc(in_sz, GFP_KERNEL);
- out = kzalloc(out_sz, GFP_KERNEL);
+ in = kvzalloc(in_sz, GFP_KERNEL);
+ out = kvzalloc(out_sz, GFP_KERNEL);
if (!in || !out) {
err = -ENOMEM;
goto out;
@@ -638,8 +638,8 @@ int mlx5_query_hca_vport_pkey(struct mlx5_core_dev *dev, u8 other_vport,
*pkey = MLX5_GET_PR(pkey, pkarr, pkey);
out:
- kfree(in);
- kfree(out);
+ kvfree(in);
+ kvfree(out);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_pkey);
@@ -658,7 +658,7 @@ int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev,
is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
- out = kzalloc(out_sz, GFP_KERNEL);
+ out = kvzalloc(out_sz, GFP_KERNEL);
if (!out)
return -ENOMEM;
@@ -717,7 +717,7 @@ int mlx5_query_hca_vport_context(struct mlx5_core_dev *dev,
system_image_guid);
ex:
- kfree(out);
+ kvfree(out);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_context);
@@ -728,7 +728,7 @@ int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev,
struct mlx5_hca_vport_context *rep;
int err;
- rep = kzalloc(sizeof(*rep), GFP_KERNEL);
+ rep = kvzalloc(sizeof(*rep), GFP_KERNEL);
if (!rep)
return -ENOMEM;
@@ -736,7 +736,7 @@ int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev,
if (!err)
*sys_image_guid = rep->sys_image_guid;
- kfree(rep);
+ kvfree(rep);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_system_image_guid);
@@ -747,7 +747,7 @@ int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
struct mlx5_hca_vport_context *rep;
int err;
- rep = kzalloc(sizeof(*rep), GFP_KERNEL);
+ rep = kvzalloc(sizeof(*rep), GFP_KERNEL);
if (!rep)
return -ENOMEM;
@@ -755,7 +755,7 @@ int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
if (!err)
*node_guid = rep->node_guid;
- kfree(rep);
+ kvfree(rep);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid);
@@ -770,7 +770,7 @@ int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
int err;
- out = kzalloc(outlen, GFP_KERNEL);
+ out = kvzalloc(outlen, GFP_KERNEL);
if (!out)
return -ENOMEM;
@@ -786,7 +786,7 @@ int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev,
nic_vport_context.promisc_all);
out:
- kfree(out);
+ kvfree(out);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_promisc);
@@ -874,7 +874,7 @@ int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, bool *status)
int value;
int err;
- out = kzalloc(outlen, GFP_KERNEL);
+ out = kvzalloc(outlen, GFP_KERNEL);
if (!out)
return -ENOMEM;
@@ -891,7 +891,7 @@ int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, bool *status)
*status = !value;
out:
- kfree(out);
+ kvfree(out);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_nic_vport_query_local_lb);
@@ -1033,7 +1033,7 @@ int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev,
mlx5_core_dbg(dev, "vf %d\n", vf);
is_group_manager = MLX5_CAP_GEN(dev, vport_group_manager);
- in = kzalloc(in_sz, GFP_KERNEL);
+ in = kvzalloc(in_sz, GFP_KERNEL);
if (!in)
return -ENOMEM;
@@ -1065,7 +1065,7 @@ int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev,
req->cap_mask1_perm);
err = mlx5_cmd_exec_in(dev, modify_hca_vport_context, in);
ex:
- kfree(in);
+ kvfree(in);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_core_modify_hca_vport_context);
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
index 66ef0090755e..84621b4cb15b 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
@@ -69,7 +69,7 @@ static void mlxbf_gige_initial_mac(struct mlxbf_gige *priv)
u8 mac[ETH_ALEN];
u64 local_mac;
- memset(mac, 0, ETH_ALEN);
+ eth_zero_addr(mac);
mlxbf_gige_get_mac_rx_filter(priv, MLXBF_GIGE_LOCAL_MAC_FILTER_IDX,
&local_mac);
u64_to_ether_addr(local_mac, mac);
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index 138718f33dbd..6ad68b422129 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -101,6 +101,24 @@ static int lan966x_create_targets(struct platform_device *pdev,
return 0;
}
+static bool lan966x_port_unique_address(struct net_device *dev)
+{
+ struct lan966x_port *port = netdev_priv(dev);
+ struct lan966x *lan966x = port->lan966x;
+ int p;
+
+ for (p = 0; p < lan966x->num_phys_ports; ++p) {
+ port = lan966x->ports[p];
+ if (!port || port->dev == dev)
+ continue;
+
+ if (ether_addr_equal(dev->dev_addr, port->dev->dev_addr))
+ return false;
+ }
+
+ return true;
+}
+
static int lan966x_port_set_mac_address(struct net_device *dev, void *p)
{
struct lan966x_port *port = netdev_priv(dev);
@@ -108,16 +126,26 @@ static int lan966x_port_set_mac_address(struct net_device *dev, void *p)
const struct sockaddr *addr = p;
int ret;
+ if (ether_addr_equal(addr->sa_data, dev->dev_addr))
+ return 0;
+
/* Learn the new net device MAC address in the mac table. */
ret = lan966x_mac_cpu_learn(lan966x, addr->sa_data, HOST_PVID);
if (ret)
return ret;
+ /* If there is another port with the same address as the dev, then don't
+ * delete it from the MAC table
+ */
+ if (!lan966x_port_unique_address(dev))
+ goto out;
+
/* Then forget the previous one. */
ret = lan966x_mac_cpu_forget(lan966x, dev->dev_addr, HOST_PVID);
if (ret)
return ret;
+out:
eth_hw_addr_set(dev, addr->sa_data);
return ret;
}
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index d2de8ac44f72..fa5d4ddf429b 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -2405,7 +2405,6 @@ static void vxge_rem_msix_isr(struct vxgedev *vdev)
for (intr_cnt = 0; intr_cnt < (vdev->no_of_vpath * 2 + 1);
intr_cnt++) {
if (vdev->vxge_entries[intr_cnt].in_use) {
- synchronize_irq(vdev->entries[intr_cnt].vector);
free_irq(vdev->entries[intr_cnt].vector,
vdev->vxge_entries[intr_cnt].arg);
vdev->vxge_entries[intr_cnt].in_use = 0;
@@ -2427,7 +2426,6 @@ static void vxge_rem_isr(struct vxgedev *vdev)
vdev->config.intr_type == MSI_X) {
vxge_rem_msix_isr(vdev);
} else if (vdev->config.intr_type == INTA) {
- synchronize_irq(vdev->pdev->irq);
free_irq(vdev->pdev->irq, vdev);
}
}
diff --git a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c
index 1edcd9f86c9c..443a5d6eb57b 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c
@@ -76,12 +76,119 @@ bool is_post_ct_flow(struct flow_cls_offload *flow)
return false;
}
+/**
+ * get_mangled_key() - Mangle the key if mangle act exists
+ * @rule: rule that carries the actions
+ * @buf: pointer to key to be mangled
+ * @offset: used to adjust mangled offset in L2/L3/L4 header
+ * @key_sz: key size
+ * @htype: mangling type
+ *
+ * Returns buf where the mangled key stores.
+ */
+static void *get_mangled_key(struct flow_rule *rule, void *buf,
+ u32 offset, size_t key_sz,
+ enum flow_action_mangle_base htype)
+{
+ struct flow_action_entry *act;
+ u32 *val = (u32 *)buf;
+ u32 off, msk, key;
+ int i;
+
+ flow_action_for_each(i, act, &rule->action) {
+ if (act->id == FLOW_ACTION_MANGLE &&
+ act->mangle.htype == htype) {
+ off = act->mangle.offset - offset;
+ msk = act->mangle.mask;
+ key = act->mangle.val;
+
+ /* Mangling is supposed to be u32 aligned */
+ if (off % 4 || off >= key_sz)
+ continue;
+
+ val[off >> 2] &= msk;
+ val[off >> 2] |= key;
+ }
+ }
+
+ return buf;
+}
+
+/* Only tos and ttl are involved in flow_match_ip structure, which
+ * doesn't conform to the layout of ip/ipv6 header definition. So
+ * they need particular process here: fill them into the ip/ipv6
+ * header, so that mangling actions can work directly.
+ */
+#define NFP_IPV4_TOS_MASK GENMASK(23, 16)
+#define NFP_IPV4_TTL_MASK GENMASK(31, 24)
+#define NFP_IPV6_TCLASS_MASK GENMASK(27, 20)
+#define NFP_IPV6_HLIMIT_MASK GENMASK(7, 0)
+static void *get_mangled_tos_ttl(struct flow_rule *rule, void *buf,
+ bool is_v6)
+{
+ struct flow_match_ip match;
+ /* IPv4's ttl field is in third dword. */
+ __be32 ip_hdr[3];
+ u32 tmp, hdr_len;
+
+ flow_rule_match_ip(rule, &match);
+
+ if (is_v6) {
+ tmp = FIELD_PREP(NFP_IPV6_TCLASS_MASK, match.key->tos);
+ ip_hdr[0] = cpu_to_be32(tmp);
+ tmp = FIELD_PREP(NFP_IPV6_HLIMIT_MASK, match.key->ttl);
+ ip_hdr[1] = cpu_to_be32(tmp);
+ hdr_len = 2 * sizeof(__be32);
+ } else {
+ tmp = FIELD_PREP(NFP_IPV4_TOS_MASK, match.key->tos);
+ ip_hdr[0] = cpu_to_be32(tmp);
+ tmp = FIELD_PREP(NFP_IPV4_TTL_MASK, match.key->ttl);
+ ip_hdr[2] = cpu_to_be32(tmp);
+ hdr_len = 3 * sizeof(__be32);
+ }
+
+ get_mangled_key(rule, ip_hdr, 0, hdr_len,
+ is_v6 ? FLOW_ACT_MANGLE_HDR_TYPE_IP6 :
+ FLOW_ACT_MANGLE_HDR_TYPE_IP4);
+
+ match.key = buf;
+
+ if (is_v6) {
+ tmp = be32_to_cpu(ip_hdr[0]);
+ match.key->tos = FIELD_GET(NFP_IPV6_TCLASS_MASK, tmp);
+ tmp = be32_to_cpu(ip_hdr[1]);
+ match.key->ttl = FIELD_GET(NFP_IPV6_HLIMIT_MASK, tmp);
+ } else {
+ tmp = be32_to_cpu(ip_hdr[0]);
+ match.key->tos = FIELD_GET(NFP_IPV4_TOS_MASK, tmp);
+ tmp = be32_to_cpu(ip_hdr[2]);
+ match.key->ttl = FIELD_GET(NFP_IPV4_TTL_MASK, tmp);
+ }
+
+ return buf;
+}
+
+/* Note entry1 and entry2 are not swappable, entry1 should be
+ * the former flow whose mangle action need be taken into account
+ * if existed, and entry2 should be the latter flow whose action
+ * we don't care.
+ */
static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1,
struct nfp_fl_ct_flow_entry *entry2)
{
unsigned int ovlp_keys = entry1->rule->match.dissector->used_keys &
entry2->rule->match.dissector->used_keys;
- bool out;
+ bool out, is_v6 = false;
+ u8 ip_proto = 0;
+ /* Temporary buffer for mangling keys, 64 is enough to cover max
+ * struct size of key in various fields that may be mangled.
+ * Supported fileds to mangle:
+ * mac_src/mac_dst(struct flow_match_eth_addrs, 12B)
+ * nw_tos/nw_ttl(struct flow_match_ip, 2B)
+ * nw_src/nw_dst(struct flow_match_ipv4/6_addrs, 32B)
+ * tp_src/tp_dst(struct flow_match_ports, 4B)
+ */
+ char buf[64];
if (entry1->netdev && entry2->netdev &&
entry1->netdev != entry2->netdev)
@@ -105,6 +212,14 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1,
flow_rule_match_basic(entry1->rule, &match1);
flow_rule_match_basic(entry2->rule, &match2);
+
+ /* n_proto field is a must in ct-related flows,
+ * it should be either ipv4 or ipv6.
+ */
+ is_v6 = match1.key->n_proto == htons(ETH_P_IPV6);
+ /* ip_proto field is a must when port field is cared */
+ ip_proto = match1.key->ip_proto;
+
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
if (out)
goto check_failed;
@@ -115,6 +230,13 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1,
flow_rule_match_ipv4_addrs(entry1->rule, &match1);
flow_rule_match_ipv4_addrs(entry2->rule, &match2);
+
+ memcpy(buf, match1.key, sizeof(*match1.key));
+ match1.key = get_mangled_key(entry1->rule, buf,
+ offsetof(struct iphdr, saddr),
+ sizeof(*match1.key),
+ FLOW_ACT_MANGLE_HDR_TYPE_IP4);
+
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
if (out)
goto check_failed;
@@ -125,16 +247,34 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1,
flow_rule_match_ipv6_addrs(entry1->rule, &match1);
flow_rule_match_ipv6_addrs(entry2->rule, &match2);
+
+ memcpy(buf, match1.key, sizeof(*match1.key));
+ match1.key = get_mangled_key(entry1->rule, buf,
+ offsetof(struct ipv6hdr, saddr),
+ sizeof(*match1.key),
+ FLOW_ACT_MANGLE_HDR_TYPE_IP6);
+
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
if (out)
goto check_failed;
}
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_PORTS)) {
+ enum flow_action_mangle_base htype = FLOW_ACT_MANGLE_UNSPEC;
struct flow_match_ports match1, match2;
flow_rule_match_ports(entry1->rule, &match1);
flow_rule_match_ports(entry2->rule, &match2);
+
+ if (ip_proto == IPPROTO_UDP)
+ htype = FLOW_ACT_MANGLE_HDR_TYPE_UDP;
+ else if (ip_proto == IPPROTO_TCP)
+ htype = FLOW_ACT_MANGLE_HDR_TYPE_TCP;
+
+ memcpy(buf, match1.key, sizeof(*match1.key));
+ match1.key = get_mangled_key(entry1->rule, buf, 0,
+ sizeof(*match1.key), htype);
+
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
if (out)
goto check_failed;
@@ -145,6 +285,12 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1,
flow_rule_match_eth_addrs(entry1->rule, &match1);
flow_rule_match_eth_addrs(entry2->rule, &match2);
+
+ memcpy(buf, match1.key, sizeof(*match1.key));
+ match1.key = get_mangled_key(entry1->rule, buf, 0,
+ sizeof(*match1.key),
+ FLOW_ACT_MANGLE_HDR_TYPE_ETH);
+
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
if (out)
goto check_failed;
@@ -185,6 +331,8 @@ static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1,
flow_rule_match_ip(entry1->rule, &match1);
flow_rule_match_ip(entry2->rule, &match2);
+
+ match1.key = get_mangled_tos_ttl(entry1->rule, buf, is_v6);
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
if (out)
goto check_failed;
@@ -256,98 +404,16 @@ check_failed:
return -EINVAL;
}
-static int nfp_ct_check_mangle_merge(struct flow_action_entry *a_in,
- struct flow_rule *rule)
-{
- enum flow_action_mangle_base htype = a_in->mangle.htype;
- u32 offset = a_in->mangle.offset;
-
- switch (htype) {
- case FLOW_ACT_MANGLE_HDR_TYPE_ETH:
- if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS))
- return -EOPNOTSUPP;
- break;
- case FLOW_ACT_MANGLE_HDR_TYPE_IP4:
- if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
- struct flow_match_ip match;
-
- flow_rule_match_ip(rule, &match);
- if (offset == offsetof(struct iphdr, ttl) &&
- match.mask->ttl)
- return -EOPNOTSUPP;
- if (offset == round_down(offsetof(struct iphdr, tos), 4) &&
- match.mask->tos)
- return -EOPNOTSUPP;
- }
- if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
- struct flow_match_ipv4_addrs match;
-
- flow_rule_match_ipv4_addrs(rule, &match);
- if (offset == offsetof(struct iphdr, saddr) &&
- match.mask->src)
- return -EOPNOTSUPP;
- if (offset == offsetof(struct iphdr, daddr) &&
- match.mask->dst)
- return -EOPNOTSUPP;
- }
- break;
- case FLOW_ACT_MANGLE_HDR_TYPE_IP6:
- if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
- struct flow_match_ip match;
-
- flow_rule_match_ip(rule, &match);
- if (offset == round_down(offsetof(struct ipv6hdr, hop_limit), 4) &&
- match.mask->ttl)
- return -EOPNOTSUPP;
- /* for ipv6, tos and flow_lbl are in the same word */
- if (offset == round_down(offsetof(struct ipv6hdr, flow_lbl), 4) &&
- match.mask->tos)
- return -EOPNOTSUPP;
- }
- if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
- struct flow_match_ipv6_addrs match;
-
- flow_rule_match_ipv6_addrs(rule, &match);
- if (offset >= offsetof(struct ipv6hdr, saddr) &&
- offset < offsetof(struct ipv6hdr, daddr) &&
- memchr_inv(&match.mask->src, 0, sizeof(match.mask->src)))
- return -EOPNOTSUPP;
- if (offset >= offsetof(struct ipv6hdr, daddr) &&
- offset < sizeof(struct ipv6hdr) &&
- memchr_inv(&match.mask->dst, 0, sizeof(match.mask->dst)))
- return -EOPNOTSUPP;
- }
- break;
- case FLOW_ACT_MANGLE_HDR_TYPE_TCP:
- case FLOW_ACT_MANGLE_HDR_TYPE_UDP:
- /* currently only can modify ports */
- if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS))
- return -EOPNOTSUPP;
- break;
- default:
- break;
- }
- return 0;
-}
-
static int nfp_ct_merge_act_check(struct nfp_fl_ct_flow_entry *pre_ct_entry,
struct nfp_fl_ct_flow_entry *post_ct_entry,
struct nfp_fl_ct_flow_entry *nft_entry)
{
struct flow_action_entry *act;
- int err, i;
+ int i;
/* Check for pre_ct->action conflicts */
flow_action_for_each(i, act, &pre_ct_entry->rule->action) {
switch (act->id) {
- case FLOW_ACTION_MANGLE:
- err = nfp_ct_check_mangle_merge(act, nft_entry->rule);
- if (err)
- return err;
- err = nfp_ct_check_mangle_merge(act, post_ct_entry->rule);
- if (err)
- return err;
- break;
case FLOW_ACTION_VLAN_PUSH:
case FLOW_ACTION_VLAN_POP:
case FLOW_ACTION_VLAN_MANGLE:
@@ -363,11 +429,6 @@ static int nfp_ct_merge_act_check(struct nfp_fl_ct_flow_entry *pre_ct_entry,
/* Check for nft->action conflicts */
flow_action_for_each(i, act, &nft_entry->rule->action) {
switch (act->id) {
- case FLOW_ACTION_MANGLE:
- err = nfp_ct_check_mangle_merge(act, post_ct_entry->rule);
- if (err)
- return err;
- break;
case FLOW_ACTION_VLAN_PUSH:
case FLOW_ACTION_VLAN_POP:
case FLOW_ACTION_VLAN_MANGLE:
@@ -924,7 +985,7 @@ static int nfp_ct_do_nft_merge(struct nfp_fl_ct_zone_entry *zt,
err = nfp_ct_merge_check(pre_ct_entry, nft_entry);
if (err)
return err;
- err = nfp_ct_merge_check(post_ct_entry, nft_entry);
+ err = nfp_ct_merge_check(nft_entry, post_ct_entry);
if (err)
return err;
err = nfp_ct_check_meta(post_ct_entry, nft_entry);
@@ -1009,7 +1070,7 @@ static int nfp_ct_do_tc_merge(struct nfp_fl_ct_zone_entry *zt,
if (post_ct_entry->chain_index != pre_ct_entry->chain_index)
return -EINVAL;
- err = nfp_ct_merge_check(post_ct_entry, pre_ct_entry);
+ err = nfp_ct_merge_check(pre_ct_entry, post_ct_entry);
if (err)
return err;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/match.c b/drivers/net/ethernet/netronome/nfp/flower/match.c
index 9d86eea4dc16..193a167a6762 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/match.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/match.c
@@ -98,16 +98,18 @@ nfp_flower_compile_mac(struct nfp_flower_mac_mpls *ext,
{
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
struct flow_match_eth_addrs match;
+ u8 tmp;
int i;
flow_rule_match_eth_addrs(rule, &match);
/* Populate mac frame. */
for (i = 0; i < ETH_ALEN; i++) {
- ext->mac_dst[i] |= match.key->dst[i] &
- match.mask->dst[i];
+ tmp = match.key->dst[i] & match.mask->dst[i];
+ ext->mac_dst[i] |= tmp & (~msk->mac_dst[i]);
msk->mac_dst[i] |= match.mask->dst[i];
- ext->mac_src[i] |= match.key->src[i] &
- match.mask->src[i];
+
+ tmp = match.key->src[i] & match.mask->src[i];
+ ext->mac_src[i] |= tmp & (~msk->mac_src[i]);
msk->mac_src[i] |= match.mask->src[i];
}
}
@@ -189,11 +191,16 @@ nfp_flower_compile_tport(struct nfp_flower_tp_ports *ext,
{
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
struct flow_match_ports match;
+ __be16 tmp;
flow_rule_match_ports(rule, &match);
- ext->port_src |= match.key->src & match.mask->src;
- ext->port_dst |= match.key->dst & match.mask->dst;
+
+ tmp = match.key->src & match.mask->src;
+ ext->port_src |= tmp & (~msk->port_src);
msk->port_src |= match.mask->src;
+
+ tmp = match.key->dst & match.mask->dst;
+ ext->port_dst |= tmp & (~msk->port_dst);
msk->port_dst |= match.mask->dst;
}
}
@@ -212,11 +219,16 @@ nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext,
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
struct flow_match_ip match;
+ u8 tmp;
flow_rule_match_ip(rule, &match);
- ext->tos |= match.key->tos & match.mask->tos;
- ext->ttl |= match.key->ttl & match.mask->ttl;
+
+ tmp = match.key->tos & match.mask->tos;
+ ext->tos |= tmp & (~msk->tos);
msk->tos |= match.mask->tos;
+
+ tmp = match.key->ttl & match.mask->ttl;
+ ext->ttl |= tmp & (~msk->ttl);
msk->ttl |= match.mask->ttl;
}
@@ -325,11 +337,16 @@ nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *ext,
{
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
struct flow_match_ipv4_addrs match;
+ __be32 tmp;
flow_rule_match_ipv4_addrs(rule, &match);
- ext->ipv4_src |= match.key->src & match.mask->src;
- ext->ipv4_dst |= match.key->dst & match.mask->dst;
+
+ tmp = match.key->src & match.mask->src;
+ ext->ipv4_src |= tmp & (~msk->ipv4_src);
msk->ipv4_src |= match.mask->src;
+
+ tmp = match.key->dst & match.mask->dst;
+ ext->ipv4_dst |= tmp & (~msk->ipv4_dst);
msk->ipv4_dst |= match.mask->dst;
}
@@ -342,15 +359,21 @@ nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *ext,
{
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
struct flow_match_ipv6_addrs match;
+ u8 tmp;
int i;
flow_rule_match_ipv6_addrs(rule, &match);
for (i = 0; i < sizeof(ext->ipv6_src); i++) {
- ext->ipv6_src.s6_addr[i] |= match.key->src.s6_addr[i] &
- match.mask->src.s6_addr[i];
- ext->ipv6_dst.s6_addr[i] |= match.key->dst.s6_addr[i] &
- match.mask->dst.s6_addr[i];
+ tmp = match.key->src.s6_addr[i] &
+ match.mask->src.s6_addr[i];
+ ext->ipv6_src.s6_addr[i] |= tmp &
+ (~msk->ipv6_src.s6_addr[i]);
msk->ipv6_src.s6_addr[i] |= match.mask->src.s6_addr[i];
+
+ tmp = match.key->dst.s6_addr[i] &
+ match.mask->dst.s6_addr[i];
+ ext->ipv6_dst.s6_addr[i] |= tmp &
+ (~msk->ipv6_dst.s6_addr[i]);
msk->ipv6_dst.s6_addr[i] |= match.mask->dst.s6_addr[i];
}
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index c5003fa1a25e..c91898be7c03 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -823,7 +823,6 @@ static void qed_slowpath_irq_free(struct qed_dev *cdev)
for_each_hwfn(cdev, i) {
if (!cdev->hwfns[i].b_int_requested)
break;
- synchronize_irq(cdev->int_params.msix_table[i].vector);
free_irq(cdev->int_params.msix_table[i].vector,
&cdev->hwfns[i].sp_dpc);
}
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index b4e5a15e308b..f56b679adb4b 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1916,7 +1916,6 @@ static void qede_sync_free_irqs(struct qede_dev *edev)
for (i = 0; i < edev->int_info.used_cnt; i++) {
if (edev->int_info.msix_cnt) {
- synchronize_irq(edev->int_info.msix[i].vector);
free_irq(edev->int_info.msix[i].vector,
&edev->fp_array[i]);
} else {
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index b30589a135c2..06f4d9a9e938 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -3614,7 +3614,8 @@ static void ql_reset_work(struct work_struct *work)
qdev->mem_map_registers;
unsigned long hw_flags;
- if (test_bit((QL_RESET_PER_SCSI | QL_RESET_START), &qdev->flags)) {
+ if (test_bit(QL_RESET_PER_SCSI, &qdev->flags) ||
+ test_bit(QL_RESET_START, &qdev->flags)) {
clear_bit(QL_LINK_MASTER, &qdev->flags);
/*
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index a69d756e09b9..b2536d2c218a 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -1008,7 +1008,8 @@ static int ef100_process_design_param(struct efx_nic *efx,
}
return 0;
case ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_LEN:
- nic_data->tso_max_payload_len = min_t(u64, reader->value, GSO_MAX_SIZE);
+ nic_data->tso_max_payload_len = min_t(u64, reader->value,
+ GSO_LEGACY_MAX_SIZE);
netif_set_tso_max_size(efx->net_dev,
nic_data->tso_max_payload_len);
return 0;
diff --git a/drivers/net/ethernet/sfc/falcon/tx.c b/drivers/net/ethernet/sfc/falcon/tx.c
index f7306e93a8b8..b9369483758c 100644
--- a/drivers/net/ethernet/sfc/falcon/tx.c
+++ b/drivers/net/ethernet/sfc/falcon/tx.c
@@ -98,7 +98,8 @@ unsigned int ef4_tx_max_skb_descs(struct ef4_nic *efx)
/* Possibly more for PCIe page boundaries within input fragments */
if (PAGE_SIZE > EF4_PAGE_SIZE)
max_descs += max_t(unsigned int, MAX_SKB_FRAGS,
- DIV_ROUND_UP(GSO_MAX_SIZE, EF4_PAGE_SIZE));
+ DIV_ROUND_UP(GSO_LEGACY_MAX_SIZE,
+ EF4_PAGE_SIZE));
return max_descs;
}
diff --git a/drivers/net/ethernet/sfc/siena/efx_channels.h b/drivers/net/ethernet/sfc/siena/efx_channels.h
index 10d78049b885..c4b95a2d770f 100644
--- a/drivers/net/ethernet/sfc/siena/efx_channels.h
+++ b/drivers/net/ethernet/sfc/siena/efx_channels.h
@@ -8,8 +8,8 @@
* by the Free Software Foundation, incorporated herein by reference.
*/
-#ifndef EFX_CHANNELS_H
-#define EFX_CHANNELS_H
+#ifndef EFX_SIENA_CHANNELS_H
+#define EFX_SIENA_CHANNELS_H
extern unsigned int efx_siena_interrupt_mode;
extern unsigned int efx_siena_rss_cpus;
diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c
index 9bc8281b7f5b..658ea2d34070 100644
--- a/drivers/net/ethernet/sfc/tx_common.c
+++ b/drivers/net/ethernet/sfc/tx_common.c
@@ -416,7 +416,8 @@ unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
/* Possibly more for PCIe page boundaries within input fragments */
if (PAGE_SIZE > EFX_PAGE_SIZE)
max_descs += max_t(unsigned int, MAX_SKB_FRAGS,
- DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE));
+ DIV_ROUND_UP(GSO_LEGACY_MAX_SIZE,
+ EFX_PAGE_SIZE));
return max_descs;
}
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index fc9cef9dcefc..24d66af797d4 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -140,7 +140,7 @@ static void PRINT_PKT(u_char *buf, int length)
pr_cont("\n");
}
#else
-#define PRINT_PKT(x...) do { } while (0)
+static inline void PRINT_PKT(u_char *buf, int length) { }
#endif
@@ -430,7 +430,7 @@ static inline void smc911x_rcv(struct net_device *dev)
SMC_PULL_DATA(lp, data, pkt_len+2+3);
DBG(SMC_DEBUG_PKTS, dev, "Received packet\n");
- PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64);
+ PRINT_PKT(data, min(pkt_len - 4, 64U));
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->stats.rx_packets++;
@@ -480,7 +480,7 @@ static void smc911x_hardware_send_pkt(struct net_device *dev)
SMC_SET_TX_FIFO(lp, cmdB);
DBG(SMC_DEBUG_PKTS, dev, "Transmitted packet\n");
- PRINT_PKT(buf, len <= 64 ? len : 64);
+ PRINT_PKT(buf, min(len, 64U));
/* Send pkt via PIO or DMA */
#ifdef SMC_USE_DMA
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index d3b4765c1a5b..8cc80b1db4cb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -462,11 +462,6 @@ static void dwmac4_set_mss_ctxt(struct dma_desc *p, unsigned int mss)
p->des3 = cpu_to_le32(TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV);
}
-static void dwmac4_get_addr(struct dma_desc *p, unsigned int *addr)
-{
- *addr = le32_to_cpu(p->des0);
-}
-
static void dwmac4_set_addr(struct dma_desc *p, dma_addr_t addr)
{
p->des0 = cpu_to_le32(lower_32_bits(addr));
@@ -575,7 +570,6 @@ const struct stmmac_desc_ops dwmac4_desc_ops = {
.init_tx_desc = dwmac4_rd_init_tx_desc,
.display_ring = dwmac4_display_ring,
.set_mss = dwmac4_set_mss_ctxt,
- .get_addr = dwmac4_get_addr,
.set_addr = dwmac4_set_addr,
.clear = dwmac4_clear,
.set_sarc = dwmac4_set_sarc,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
index ccfb0102dde4..b1f0c3984a09 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
@@ -239,11 +239,6 @@ static void dwxgmac2_set_mss(struct dma_desc *p, unsigned int mss)
p->des3 = cpu_to_le32(XGMAC_TDES3_CTXT | XGMAC_TDES3_TCMSSV);
}
-static void dwxgmac2_get_addr(struct dma_desc *p, unsigned int *addr)
-{
- *addr = le32_to_cpu(p->des0);
-}
-
static void dwxgmac2_set_addr(struct dma_desc *p, dma_addr_t addr)
{
p->des0 = cpu_to_le32(lower_32_bits(addr));
@@ -366,7 +361,6 @@ const struct stmmac_desc_ops dwxgmac210_desc_ops = {
.init_rx_desc = dwxgmac2_init_rx_desc,
.init_tx_desc = dwxgmac2_init_tx_desc,
.set_mss = dwxgmac2_set_mss,
- .get_addr = dwxgmac2_get_addr,
.set_addr = dwxgmac2_set_addr,
.clear = dwxgmac2_clear,
.get_rx_hash = dwxgmac2_get_rx_hash,
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index 6650edfab5bc..1bcbbd724fb5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -440,11 +440,6 @@ static void enh_desc_display_ring(void *head, unsigned int size, bool rx,
pr_info("\n");
}
-static void enh_desc_get_addr(struct dma_desc *p, unsigned int *addr)
-{
- *addr = le32_to_cpu(p->des2);
-}
-
static void enh_desc_set_addr(struct dma_desc *p, dma_addr_t addr)
{
p->des2 = cpu_to_le32(addr);
@@ -475,7 +470,6 @@ const struct stmmac_desc_ops enh_desc_ops = {
.get_timestamp = enh_desc_get_timestamp,
.get_rx_timestamp_status = enh_desc_get_rx_timestamp_status,
.display_ring = enh_desc_display_ring,
- .get_addr = enh_desc_get_addr,
.set_addr = enh_desc_set_addr,
.clear = enh_desc_clear,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index f7dc447f05a0..592b4067f9b8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -82,8 +82,6 @@ struct stmmac_desc_ops {
dma_addr_t dma_rx_phy, unsigned int desc_size);
/* set MSS via context descriptor */
void (*set_mss)(struct dma_desc *p, unsigned int mss);
- /* get descriptor skbuff address */
- void (*get_addr)(struct dma_desc *p, unsigned int *addr);
/* set descriptor skbuff address */
void (*set_addr)(struct dma_desc *p, dma_addr_t addr);
/* clear descriptor */
@@ -142,8 +140,6 @@ struct stmmac_desc_ops {
stmmac_do_void_callback(__priv, desc, display_ring, __args)
#define stmmac_set_mss(__priv, __args...) \
stmmac_do_void_callback(__priv, desc, set_mss, __args)
-#define stmmac_get_desc_addr(__priv, __args...) \
- stmmac_do_void_callback(__priv, desc, get_addr, __args)
#define stmmac_set_desc_addr(__priv, __args...) \
stmmac_do_void_callback(__priv, desc, set_addr, __args)
#define stmmac_clear_desc(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 98ef43f35802..e3da4da242ee 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -292,11 +292,6 @@ static void ndesc_display_ring(void *head, unsigned int size, bool rx,
pr_info("\n");
}
-static void ndesc_get_addr(struct dma_desc *p, unsigned int *addr)
-{
- *addr = le32_to_cpu(p->des2);
-}
-
static void ndesc_set_addr(struct dma_desc *p, dma_addr_t addr)
{
p->des2 = cpu_to_le32(addr);
@@ -326,7 +321,6 @@ const struct stmmac_desc_ops ndesc_ops = {
.get_timestamp = ndesc_get_timestamp,
.get_rx_timestamp_status = ndesc_get_rx_timestamp_status,
.display_ring = ndesc_display_ring,
- .get_addr = ndesc_get_addr,
.set_addr = ndesc_set_addr,
.clear = ndesc_clear,
};
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index b04a6a7bf566..435dc00d04e5 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -1313,7 +1313,7 @@ static void cas_init_rx_dma(struct cas *cp)
writel(val, cp->regs + REG_RX_PAGE_SIZE);
/* enable the header parser if desired */
- if (CAS_HP_FIRMWARE == cas_prog_null)
+ if (&CAS_HP_FIRMWARE[0] == &cas_prog_null[0])
return;
val = CAS_BASE(HP_CFG_NUM_CPU, CAS_NCPUS > 63 ? 0 : CAS_NCPUS);
@@ -3780,7 +3780,7 @@ static void cas_reset(struct cas *cp, int blkflag)
/* program header parser */
if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) ||
- (CAS_HP_ALT_FIRMWARE == cas_prog_null)) {
+ (&CAS_HP_ALT_FIRMWARE[0] == &cas_prog_null[0])) {
cas_load_firmware(cp, CAS_HP_FIRMWARE);
} else {
cas_load_firmware(cp, CAS_HP_ALT_FIRMWARE);
diff --git a/drivers/net/ethernet/sunplus/Kconfig b/drivers/net/ethernet/sunplus/Kconfig
index d0144a2ab918..be50a6b723eb 100644
--- a/drivers/net/ethernet/sunplus/Kconfig
+++ b/drivers/net/ethernet/sunplus/Kconfig
@@ -23,9 +23,6 @@ config SP7021_EMAC
tristate "Sunplus Dual 10M/100M Ethernet devices"
depends on SOC_SP7021 || COMPILE_TEST
select PHYLIB
- select COMMON_CLK_SP7021
- select RESET_SUNPLUS
- select NVMEM_SUNPLUS_OCOTP
help
If you have Sunplus dual 10M/100M Ethernet devices, say Y.
The network device creates two net-device interfaces.
diff --git a/drivers/net/ethernet/sunplus/spl2sw_int.c b/drivers/net/ethernet/sunplus/spl2sw_int.c
index 69b1e2e0271e..a37c9a4c281f 100644
--- a/drivers/net/ethernet/sunplus/spl2sw_int.c
+++ b/drivers/net/ethernet/sunplus/spl2sw_int.c
@@ -29,6 +29,7 @@ int spl2sw_rx_poll(struct napi_struct *napi, int budget)
u32 mask;
int port;
u32 cmd;
+ u32 len;
/* Process high-priority queue and then low-priority queue. */
for (queue = 0; queue < RX_DESC_QUEUE_NUM; queue++) {
@@ -63,10 +64,11 @@ int spl2sw_rx_poll(struct napi_struct *napi, int budget)
skb_put(skb, pkg_len - 4); /* Minus FCS */
skb->ip_summed = CHECKSUM_NONE;
skb->protocol = eth_type_trans(skb, comm->ndev[port]);
+ len = skb->len;
netif_receive_skb(skb);
stats->rx_packets++;
- stats->rx_bytes += skb->len;
+ stats->rx_bytes += len;
/* Allocate a new skb for receiving. */
new_skb = netdev_alloc_skb(NULL, comm->rx_desc_buff_size);
diff --git a/drivers/net/ethernet/sunplus/spl2sw_mdio.c b/drivers/net/ethernet/sunplus/spl2sw_mdio.c
index 139ac8f2685e..733ae1704269 100644
--- a/drivers/net/ethernet/sunplus/spl2sw_mdio.c
+++ b/drivers/net/ethernet/sunplus/spl2sw_mdio.c
@@ -97,8 +97,10 @@ u32 spl2sw_mdio_init(struct spl2sw_common *comm)
/* Allocate and register mdio bus. */
mii_bus = devm_mdiobus_alloc(&comm->pdev->dev);
- if (!mii_bus)
- return -ENOMEM;
+ if (!mii_bus) {
+ ret = -ENOMEM;
+ goto out;
+ }
mii_bus->name = "sunplus_mii_bus";
mii_bus->parent = &comm->pdev->dev;
@@ -110,10 +112,13 @@ u32 spl2sw_mdio_init(struct spl2sw_common *comm)
ret = of_mdiobus_register(mii_bus, mdio_np);
if (ret) {
dev_err(&comm->pdev->dev, "Failed to register mdiobus!\n");
- return ret;
+ goto out;
}
comm->mii_bus = mii_bus;
+
+out:
+ of_node_put(mdio_np);
return ret;
}
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac.h b/drivers/net/ethernet/synopsys/dwc-xlgmac.h
index 98e3a271e017..a848e10f3ea4 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac.h
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac.h
@@ -38,7 +38,8 @@
#define XLGMAC_RX_DESC_MAX_DIRTY (XLGMAC_RX_DESC_CNT >> 3)
/* Descriptors required for maximum contiguous TSO/GSO packet */
-#define XLGMAC_TX_MAX_SPLIT ((GSO_MAX_SIZE / XLGMAC_TX_MAX_BUF_SIZE) + 1)
+#define XLGMAC_TX_MAX_SPLIT \
+ ((GSO_LEGACY_MAX_SIZE / XLGMAC_TX_MAX_BUF_SIZE) + 1)
/* Maximum possible descriptors needed for a SKB */
#define XLGMAC_TX_MAX_DESC_NR (MAX_SKB_FRAGS + XLGMAC_TX_MAX_SPLIT + 2)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c
index aa32dd905e2b..e162771893af 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-qos.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c
@@ -166,8 +166,7 @@ static void am65_cpsw_admin_to_oper(struct net_device *ndev)
{
struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
- if (port->qos.est_oper)
- devm_kfree(&ndev->dev, port->qos.est_oper);
+ devm_kfree(&ndev->dev, port->qos.est_oper);
port->qos.est_oper = port->qos.est_admin;
port->qos.est_admin = NULL;
@@ -434,11 +433,8 @@ static void am65_cpsw_purge_est(struct net_device *ndev)
am65_cpsw_stop_est(ndev);
- if (port->qos.est_admin)
- devm_kfree(&ndev->dev, port->qos.est_admin);
-
- if (port->qos.est_oper)
- devm_kfree(&ndev->dev, port->qos.est_oper);
+ devm_kfree(&ndev->dev, port->qos.est_admin);
+ devm_kfree(&ndev->dev, port->qos.est_oper);
port->qos.est_oper = NULL;
port->qos.est_admin = NULL;
@@ -524,8 +520,7 @@ static int am65_cpsw_set_taprio(struct net_device *ndev, void *type_data)
ret = am65_cpsw_configure_taprio(ndev, est_new);
if (!ret) {
if (taprio->enable) {
- if (port->qos.est_admin)
- devm_kfree(&ndev->dev, port->qos.est_admin);
+ devm_kfree(&ndev->dev, port->qos.est_admin);
port->qos.est_admin = est_new;
} else {
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 866af2cc27a3..6da36cb8af80 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1349,7 +1349,7 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
struct net_device_context *net_device_ctx = netdev_priv(net);
struct ndis_offload hwcaps;
struct ndis_offload_params offloads;
- unsigned int gso_max_size = GSO_MAX_SIZE;
+ unsigned int gso_max_size = GSO_LEGACY_MAX_SIZE;
int ret;
/* Find HW offload capabilities */
diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c
index db4cb2de218c..bc6e04bd00e1 100644
--- a/drivers/net/ipa/gsi.c
+++ b/drivers/net/ipa/gsi.c
@@ -1367,9 +1367,10 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
struct gsi_event *event_done;
struct gsi_event *event;
struct gsi_trans *trans;
+ u32 trans_count = 0;
u32 byte_count = 0;
- u32 old_index;
u32 event_avail;
+ u32 old_index;
trans_info = &channel->trans_info;
@@ -1390,6 +1391,7 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
do {
trans->len = __le16_to_cpu(event->len);
byte_count += trans->len;
+ trans_count++;
/* Move on to the next event and transaction */
if (--event_avail)
@@ -1401,7 +1403,7 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
/* We record RX bytes when they are received */
channel->byte_count += byte_count;
- channel->trans_count++;
+ channel->trans_count += trans_count;
}
/* Initialize a ring, including allocating DMA memory for its entries */
diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c
index e133eb2bebcf..53764f3c0c7e 100644
--- a/drivers/net/ipa/ipa_endpoint.c
+++ b/drivers/net/ipa/ipa_endpoint.c
@@ -1153,13 +1153,12 @@ static void ipa_endpoint_skb_copy(struct ipa_endpoint *endpoint,
return;
skb = __dev_alloc_skb(len, GFP_ATOMIC);
- if (!skb)
- return;
-
- /* Copy the data into the socket buffer and receive it */
- skb_put(skb, len);
- memcpy(skb->data, data, len);
- skb->truesize += extra;
+ if (skb) {
+ /* Copy the data into the socket buffer and receive it */
+ skb_put(skb, len);
+ memcpy(skb->data, data, len);
+ skb->truesize += extra;
+ }
ipa_modem_skb_rx(endpoint->netdev, skb);
}
diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c
index b35170a93b0f..307bed2ee707 100644
--- a/drivers/net/ipa/ipa_interrupt.c
+++ b/drivers/net/ipa/ipa_interrupt.c
@@ -191,7 +191,8 @@ void ipa_interrupt_add(struct ipa_interrupt *interrupt,
struct ipa *ipa = interrupt->ipa;
u32 offset;
- WARN_ON(ipa_irq >= IPA_IRQ_COUNT);
+ if (WARN_ON(ipa_irq >= IPA_IRQ_COUNT))
+ return;
interrupt->handler[ipa_irq] = handler;
@@ -208,7 +209,8 @@ ipa_interrupt_remove(struct ipa_interrupt *interrupt, enum ipa_irq_id ipa_irq)
struct ipa *ipa = interrupt->ipa;
u32 offset;
- WARN_ON(ipa_irq >= IPA_IRQ_COUNT);
+ if (WARN_ON(ipa_irq >= IPA_IRQ_COUNT))
+ return;
/* Update the IPA interrupt mask to disable it */
interrupt->enabled &= ~BIT(ipa_irq);
diff --git a/drivers/net/ipa/ipa_qmi.c b/drivers/net/ipa/ipa_qmi.c
index 90f3aec55b36..ec010cf2e816 100644
--- a/drivers/net/ipa/ipa_qmi.c
+++ b/drivers/net/ipa/ipa_qmi.c
@@ -125,7 +125,7 @@ static void ipa_qmi_indication(struct ipa_qmi *ipa_qmi)
*/
static void ipa_qmi_ready(struct ipa_qmi *ipa_qmi)
{
- struct ipa *ipa = container_of(ipa_qmi, struct ipa, qmi);
+ struct ipa *ipa;
int ret;
/* We aren't ready until the modem and microcontroller are */
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 720394c0639b..14e8d04cb434 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -191,6 +191,8 @@ static void gen_lo_setup(struct net_device *dev,
dev->netdev_ops = dev_ops;
dev->needs_free_netdev = true;
dev->priv_destructor = dev_destructor;
+
+ netif_set_tso_max_size(dev, GSO_MAX_SIZE);
}
/* The loopback device is special. There is only one instance
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
index 5ce6da62cc8e..ee374a85544a 100644
--- a/drivers/net/phy/adin.c
+++ b/drivers/net/phy/adin.c
@@ -99,6 +99,15 @@
#define ADIN1300_GE_SOFT_RESET_REG 0xff0c
#define ADIN1300_GE_SOFT_RESET BIT(0)
+#define ADIN1300_GE_CLK_CFG_REG 0xff1f
+#define ADIN1300_GE_CLK_CFG_MASK GENMASK(5, 0)
+#define ADIN1300_GE_CLK_CFG_RCVR_125 BIT(5)
+#define ADIN1300_GE_CLK_CFG_FREE_125 BIT(4)
+#define ADIN1300_GE_CLK_CFG_REF_EN BIT(3)
+#define ADIN1300_GE_CLK_CFG_HRT_RCVR BIT(2)
+#define ADIN1300_GE_CLK_CFG_HRT_FREE BIT(1)
+#define ADIN1300_GE_CLK_CFG_25 BIT(0)
+
#define ADIN1300_GE_RGMII_CFG_REG 0xff23
#define ADIN1300_GE_RGMII_RX_MSK GENMASK(8, 6)
#define ADIN1300_GE_RGMII_RX_SEL(x) \
@@ -433,6 +442,33 @@ static int adin_set_tunable(struct phy_device *phydev,
}
}
+static int adin_config_clk_out(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ const char *val = NULL;
+ u8 sel = 0;
+
+ device_property_read_string(dev, "adi,phy-output-clock", &val);
+ if (!val) {
+ /* property not present, do not enable GP_CLK pin */
+ } else if (strcmp(val, "25mhz-reference") == 0) {
+ sel |= ADIN1300_GE_CLK_CFG_25;
+ } else if (strcmp(val, "125mhz-free-running") == 0) {
+ sel |= ADIN1300_GE_CLK_CFG_FREE_125;
+ } else if (strcmp(val, "adaptive-free-running") == 0) {
+ sel |= ADIN1300_GE_CLK_CFG_HRT_FREE;
+ } else {
+ phydev_err(phydev, "invalid adi,phy-output-clock\n");
+ return -EINVAL;
+ }
+
+ if (device_property_read_bool(dev, "adi,phy-output-reference-clock"))
+ sel |= ADIN1300_GE_CLK_CFG_REF_EN;
+
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_GE_CLK_CFG_REG,
+ ADIN1300_GE_CLK_CFG_MASK, sel);
+}
+
static int adin_config_init(struct phy_device *phydev)
{
int rc;
@@ -455,6 +491,10 @@ static int adin_config_init(struct phy_device *phydev)
if (rc < 0)
return rc;
+ rc = adin_config_clk_out(phydev);
+ if (rc < 0)
+ return rc;
+
phydev_dbg(phydev, "PHY is using mode '%s'\n",
phy_modes(phydev->interface));
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 47e83c1e9051..d777c8851ed6 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -1191,7 +1191,44 @@ static int m88e1318_config_init(struct phy_device *phydev)
static int m88e1510_config_init(struct phy_device *phydev)
{
+ static const struct {
+ u16 reg17, reg16;
+ } errata_vals[] = {
+ { 0x214b, 0x2144 },
+ { 0x0c28, 0x2146 },
+ { 0xb233, 0x214d },
+ { 0xcc0c, 0x2159 },
+ };
int err;
+ int i;
+
+ /* As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512/
+ * 88E1514 Rev A0, Errata Section 5.1:
+ * If EEE is intended to be used, the following register writes
+ * must be done once after every hardware reset.
+ */
+ err = marvell_set_page(phydev, 0x00FF);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < ARRAY_SIZE(errata_vals); ++i) {
+ err = phy_write(phydev, 17, errata_vals[i].reg17);
+ if (err)
+ return err;
+ err = phy_write(phydev, 16, errata_vals[i].reg16);
+ if (err)
+ return err;
+ }
+
+ err = marvell_set_page(phydev, 0x00FB);
+ if (err < 0)
+ return err;
+ err = phy_write(phydev, 07, 0xC00D);
+ if (err < 0)
+ return err;
+ err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
+ if (err < 0)
+ return err;
/* SGMII-to-Copper mode initialization */
if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index c34a93403d1e..22139901f01c 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -520,7 +520,7 @@ static int kszphy_config_reset(struct phy_device *phydev)
}
}
- if (priv->led_mode >= 0)
+ if (priv->type && priv->led_mode >= 0)
kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode);
return 0;
@@ -536,10 +536,10 @@ static int kszphy_config_init(struct phy_device *phydev)
type = priv->type;
- if (type->has_broadcast_disable)
+ if (type && type->has_broadcast_disable)
kszphy_broadcast_disable(phydev);
- if (type->has_nand_tree_disable)
+ if (type && type->has_nand_tree_disable)
kszphy_nand_tree_disable(phydev);
return kszphy_config_reset(phydev);
@@ -1730,7 +1730,7 @@ static int kszphy_probe(struct phy_device *phydev)
priv->type = type;
- if (type->led_mode_reg) {
+ if (type && type->led_mode_reg) {
ret = of_property_read_u32(np, "micrel,led-mode",
&priv->led_mode);
if (ret)
@@ -1751,7 +1751,8 @@ static int kszphy_probe(struct phy_device *phydev)
unsigned long rate = clk_get_rate(clk);
bool rmii_ref_clk_sel_25_mhz;
- priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
+ if (type)
+ priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
rmii_ref_clk_sel_25_mhz = of_property_read_bool(np,
"micrel,rmii-reference-clock-select-25-mhz");
@@ -3018,11 +3019,12 @@ static struct phy_driver ksphy_driver[] = {
.name = "Micrel KSZ8061",
.phy_id_mask = MICREL_PHY_ID_MASK,
/* PHY_BASIC_FEATURES */
+ .probe = kszphy_probe,
.config_init = ksz8061_config_init,
.config_intr = kszphy_config_intr,
.handle_interrupt = kszphy_handle_interrupt,
- .suspend = genphy_suspend,
- .resume = genphy_resume,
+ .suspend = kszphy_suspend,
+ .resume = kszphy_resume,
}, {
.phy_id = PHY_ID_KSZ9021,
.phy_id_mask = 0x000ffffe,
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 1b41cd9732d7..ce2cbb5903d7 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -988,6 +988,7 @@ static int pppoe_fill_forward_path(struct net_device_path_ctx *ctx,
path->encap.proto = htons(ETH_P_PPP_SES);
path->encap.id = be16_to_cpu(po->num);
memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN);
+ memcpy(ctx->daddr, po->pppoe_pa.remote, ETH_ALEN);
path->dev = ctx->dev;
ctx->dev = dev;
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index c2da3438387c..7389d6ef8569 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -771,7 +771,9 @@ enum rtl8152_flags {
};
#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
+#define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN3 0x3062
struct tally_counter {
__le64 tx_packets;
@@ -9562,6 +9564,29 @@ u8 rtl8152_get_version(struct usb_interface *intf)
}
EXPORT_SYMBOL_GPL(rtl8152_get_version);
+static bool rtl8152_supports_lenovo_macpassthru(struct usb_device *udev)
+{
+ int parent_vendor_id = le16_to_cpu(udev->parent->descriptor.idVendor);
+ int product_id = le16_to_cpu(udev->descriptor.idProduct);
+ int vendor_id = le16_to_cpu(udev->descriptor.idVendor);
+
+ if (vendor_id == VENDOR_ID_LENOVO) {
+ switch (product_id) {
+ case DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2:
+ case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2:
+ case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN3:
+ case DEVICE_ID_THINKPAD_USB_C_DONGLE:
+ return 1;
+ }
+ } else if (vendor_id == VENDOR_ID_REALTEK && parent_vendor_id == VENDOR_ID_LENOVO) {
+ switch (product_id) {
+ case 0x8153:
+ return 1;
+ }
+ }
+ return 0;
+}
+
static int rtl8152_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -9642,13 +9667,7 @@ static int rtl8152_probe(struct usb_interface *intf,
netdev->hw_features &= ~NETIF_F_RXCSUM;
}
- if (le16_to_cpu(udev->descriptor.idVendor) == VENDOR_ID_LENOVO) {
- switch (le16_to_cpu(udev->descriptor.idProduct)) {
- case DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2:
- case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2:
- tp->lenovo_macpassthru = 1;
- }
- }
+ tp->lenovo_macpassthru = rtl8152_supports_lenovo_macpassthru(udev);
if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 && udev->serial &&
(!strcmp(udev->serial, "000001000000") ||
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index f474e79a7745..466da01ba2e3 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1647,6 +1647,7 @@ static void veth_setup(struct net_device *dev)
dev->hw_features = VETH_FEATURES;
dev->hw_enc_features = VETH_FEATURES;
dev->mpls_features = NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE;
+ netif_set_tso_max_size(dev, GSO_MAX_SIZE);
}
/*
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index d9d90baac72a..93e8d119d45f 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -589,6 +589,7 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
if (dma_mapping_error(&adapter->pdev->dev,
rbi->dma_addr)) {
dev_kfree_skb_any(rbi->skb);
+ rbi->skb = NULL;
rq->stats.rx_buf_alloc_failure++;
break;
}
@@ -613,6 +614,7 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
if (dma_mapping_error(&adapter->pdev->dev,
rbi->dma_addr)) {
put_page(rbi->page);
+ rbi->page = NULL;
rq->stats.rx_buf_alloc_failure++;
break;
}
@@ -1666,6 +1668,10 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq,
u32 i, ring_idx;
struct Vmxnet3_RxDesc *rxd;
+ /* ring has already been cleaned up */
+ if (!rq->rx_ring[0].base)
+ return;
+
for (ring_idx = 0; ring_idx < 2; ring_idx++) {
for (i = 0; i < rq->rx_ring[ring_idx].size; i++) {
#ifdef __BIG_ENDIAN_BITFIELD
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index abf3e5c87ca7..a61cf6c90343 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_WLAN_VENDOR_MARVELL) += marvell/
obj-$(CONFIG_WLAN_VENDOR_MEDIATEK) += mediatek/
obj-$(CONFIG_WLAN_VENDOR_MICROCHIP) += microchip/
obj-$(CONFIG_WLAN_VENDOR_PURELIFI) += purelifi/
+obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/
obj-$(CONFIG_WLAN_VENDOR_RALINK) += ralink/
obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/
obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
@@ -21,7 +22,6 @@ obj-$(CONFIG_WLAN_VENDOR_SILABS) += silabs/
obj-$(CONFIG_WLAN_VENDOR_ST) += st/
obj-$(CONFIG_WLAN_VENDOR_TI) += ti/
obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/
-obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 2092bfd02cd1..688177453b07 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1233,6 +1233,7 @@ success:
static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
{
const struct firmware *fw;
+ char boardname[100];
if (bd_ie_type == ATH10K_BD_IE_BOARD) {
if (!ar->hw_params.fw.board) {
@@ -1240,9 +1241,19 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
return -EINVAL;
}
+ scnprintf(boardname, sizeof(boardname), "board-%s-%s.bin",
+ ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
+
ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
ar->hw_params.fw.dir,
- ar->hw_params.fw.board);
+ boardname);
+ if (IS_ERR(ar->normal_mode_fw.board)) {
+ fw = ath10k_fetch_fw_file(ar,
+ ar->hw_params.fw.dir,
+ ar->hw_params.fw.board);
+ ar->normal_mode_fw.board = fw;
+ }
+
if (IS_ERR(ar->normal_mode_fw.board))
return PTR_ERR(ar->normal_mode_fw.board);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 06a51a48c1d9..3570a5895ea8 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2692,8 +2692,10 @@ static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar,
struct ieee80211_sta *sta)
{
+ struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
+
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
- switch (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
+ switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
return MODE_11AC_VHT160;
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
@@ -6926,6 +6928,9 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
struct ieee80211_sta *sta,
u32 rate_ctrl_flag, u8 nss)
{
+ struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
+ struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
+
if (nss > sta->deflink.rx_nss) {
ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n",
nss, sta->deflink.rx_nss);
@@ -6933,19 +6938,19 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
}
if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) {
- if (!sta->deflink.vht_cap.vht_supported) {
+ if (!vht_cap->vht_supported) {
ath10k_warn(ar, "Invalid VHT rate for sta %pM\n",
sta->addr);
return -EINVAL;
}
} else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) {
- if (!sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported) {
+ if (!ht_cap->ht_supported || vht_cap->vht_supported) {
ath10k_warn(ar, "Invalid HT rate for sta %pM\n",
sta->addr);
return -EINVAL;
}
} else {
- if (sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported)
+ if (ht_cap->ht_supported || vht_cap->vht_supported)
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 050bda828966..fa11807f48a9 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -9,6 +9,8 @@
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
+#include <linux/of_address.h>
+#include <linux/iommu.h>
#include "ahb.h"
#include "debug.h"
#include "hif.h"
@@ -757,6 +759,172 @@ static int ath11k_ahb_setup_resources(struct ath11k_base *ab)
return 0;
}
+static int ath11k_ahb_setup_msa_resources(struct ath11k_base *ab)
+{
+ struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
+ struct device *dev = ab->dev;
+ struct device_node *node;
+ struct resource r;
+ int ret;
+
+ node = of_parse_phandle(dev->of_node, "memory-region", 0);
+ if (!node)
+ return -ENOENT;
+
+ ret = of_address_to_resource(node, 0, &r);
+ of_node_put(node);
+ if (ret) {
+ dev_err(dev, "failed to resolve msa fixed region\n");
+ return ret;
+ }
+
+ ab_ahb->fw.msa_paddr = r.start;
+ ab_ahb->fw.msa_size = resource_size(&r);
+
+ node = of_parse_phandle(dev->of_node, "memory-region", 1);
+ if (!node)
+ return -ENOENT;
+
+ ret = of_address_to_resource(node, 0, &r);
+ of_node_put(node);
+ if (ret) {
+ dev_err(dev, "failed to resolve ce fixed region\n");
+ return ret;
+ }
+
+ ab_ahb->fw.ce_paddr = r.start;
+ ab_ahb->fw.ce_size = resource_size(&r);
+
+ return 0;
+}
+
+static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab)
+{
+ struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
+ struct device *host_dev = ab->dev;
+ struct platform_device_info info = {0};
+ struct iommu_domain *iommu_dom;
+ struct platform_device *pdev;
+ struct device_node *node;
+ int ret;
+
+ /* Chipsets not requiring MSA need not initialize
+ * MSA resources, return success in such cases.
+ */
+ if (!ab->hw_params.fixed_fw_mem)
+ return 0;
+
+ ret = ath11k_ahb_setup_msa_resources(ab);
+ if (ret) {
+ ath11k_err(ab, "failed to setup msa resources\n");
+ return ret;
+ }
+
+ node = of_get_child_by_name(host_dev->of_node, "wifi-firmware");
+ if (!node) {
+ ab_ahb->fw.use_tz = true;
+ return 0;
+ }
+
+ info.fwnode = &node->fwnode;
+ info.parent = host_dev;
+ info.name = node->name;
+ info.dma_mask = DMA_BIT_MASK(32);
+
+ pdev = platform_device_register_full(&info);
+ if (IS_ERR(pdev)) {
+ of_node_put(node);
+ return PTR_ERR(pdev);
+ }
+
+ ret = of_dma_configure(&pdev->dev, node, true);
+ if (ret) {
+ ath11k_err(ab, "dma configure fail: %d\n", ret);
+ goto err_unregister;
+ }
+
+ ab_ahb->fw.dev = &pdev->dev;
+
+ iommu_dom = iommu_domain_alloc(&platform_bus_type);
+ if (!iommu_dom) {
+ ath11k_err(ab, "failed to allocate iommu domain\n");
+ ret = -ENOMEM;
+ goto err_unregister;
+ }
+
+ ret = iommu_attach_device(iommu_dom, ab_ahb->fw.dev);
+ if (ret) {
+ ath11k_err(ab, "could not attach device: %d\n", ret);
+ goto err_iommu_free;
+ }
+
+ ret = iommu_map(iommu_dom, ab_ahb->fw.msa_paddr,
+ ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size,
+ IOMMU_READ | IOMMU_WRITE);
+ if (ret) {
+ ath11k_err(ab, "failed to map firmware region: %d\n", ret);
+ goto err_iommu_detach;
+ }
+
+ ret = iommu_map(iommu_dom, ab_ahb->fw.ce_paddr,
+ ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size,
+ IOMMU_READ | IOMMU_WRITE);
+ if (ret) {
+ ath11k_err(ab, "failed to map firmware CE region: %d\n", ret);
+ goto err_iommu_unmap;
+ }
+
+ ab_ahb->fw.use_tz = false;
+ ab_ahb->fw.iommu_domain = iommu_dom;
+ of_node_put(node);
+
+ return 0;
+
+err_iommu_unmap:
+ iommu_unmap(iommu_dom, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size);
+
+err_iommu_detach:
+ iommu_detach_device(iommu_dom, ab_ahb->fw.dev);
+
+err_iommu_free:
+ iommu_domain_free(iommu_dom);
+
+err_unregister:
+ platform_device_unregister(pdev);
+ of_node_put(node);
+
+ return ret;
+}
+
+static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
+{
+ struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
+ struct iommu_domain *iommu;
+ size_t unmapped_size;
+
+ if (ab_ahb->fw.use_tz)
+ return 0;
+
+ iommu = ab_ahb->fw.iommu_domain;
+
+ unmapped_size = iommu_unmap(iommu, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size);
+ if (unmapped_size != ab_ahb->fw.msa_size)
+ ath11k_err(ab, "failed to unmap firmware: %zu\n",
+ unmapped_size);
+
+ unmapped_size = iommu_unmap(iommu, ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size);
+ if (unmapped_size != ab_ahb->fw.ce_size)
+ ath11k_err(ab, "failed to unmap firmware CE memory: %zu\n",
+ unmapped_size);
+
+ iommu_detach_device(iommu, ab_ahb->fw.dev);
+ iommu_domain_free(iommu);
+
+ platform_device_unregister(to_platform_device(ab_ahb->fw.dev));
+
+ return 0;
+}
+
static int ath11k_ahb_probe(struct platform_device *pdev)
{
struct ath11k_base *ab;
@@ -816,10 +984,14 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
if (ret)
goto err_core_free;
- ret = ath11k_hal_srng_init(ab);
+ ret = ath11k_ahb_fw_resources_init(ab);
if (ret)
goto err_core_free;
+ ret = ath11k_hal_srng_init(ab);
+ if (ret)
+ goto err_fw_deinit;
+
ret = ath11k_ce_alloc_pipes(ab);
if (ret) {
ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
@@ -856,6 +1028,9 @@ err_ce_free:
err_hal_srng_deinit:
ath11k_hal_srng_deinit(ab);
+err_fw_deinit:
+ ath11k_ahb_fw_resource_deinit(ab);
+
err_core_free:
ath11k_core_free(ab);
platform_set_drvdata(pdev, NULL);
@@ -891,6 +1066,7 @@ static int ath11k_ahb_remove(struct platform_device *pdev)
qmi_fail:
ath11k_ahb_free_irq(ab);
ath11k_hal_srng_deinit(ab);
+ ath11k_ahb_fw_resource_deinit(ab);
ath11k_ce_free_pipes(ab);
ath11k_core_free(ab);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/wireless/ath/ath11k/ahb.h b/drivers/net/wireless/ath/ath11k/ahb.h
index 51e6e4a5f686..58a945411c5b 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.h
+++ b/drivers/net/wireless/ath/ath11k/ahb.h
@@ -12,6 +12,15 @@ struct ath11k_base;
struct ath11k_ahb {
struct rproc *tgt_rproc;
+ struct {
+ struct device *dev;
+ struct iommu_domain *iommu_domain;
+ dma_addr_t msa_paddr;
+ u32 msa_size;
+ dma_addr_t ce_paddr;
+ u32 ce_size;
+ bool use_tz;
+ } fw;
};
static inline struct ath11k_ahb *ath11k_ahb_priv(struct ath11k_base *ab)
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 01e1d494b527..1e98ff9ff288 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -110,6 +110,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.dp_window_idx = 0,
.ce_window_idx = 0,
.fixed_fw_mem = false,
+ .support_off_channel_tx = false,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -185,6 +186,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.dp_window_idx = 0,
.ce_window_idx = 0,
.fixed_fw_mem = false,
+ .support_off_channel_tx = false,
},
{
.name = "qca6390 hw2.0",
@@ -259,6 +261,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.dp_window_idx = 0,
.ce_window_idx = 0,
.fixed_fw_mem = false,
+ .support_off_channel_tx = true,
},
{
.name = "qcn9074 hw1.0",
@@ -333,6 +336,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.dp_window_idx = 3,
.ce_window_idx = 2,
.fixed_fw_mem = false,
+ .support_off_channel_tx = false,
},
{
.name = "wcn6855 hw2.0",
@@ -407,6 +411,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.dp_window_idx = 0,
.ce_window_idx = 0,
.fixed_fw_mem = false,
+ .support_off_channel_tx = true,
},
{
.name = "wcn6855 hw2.1",
@@ -480,6 +485,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.dp_window_idx = 0,
.ce_window_idx = 0,
.fixed_fw_mem = false,
+ .support_off_channel_tx = true,
},
{
.name = "wcn6750 hw1.0",
@@ -553,6 +559,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.dp_window_idx = 1,
.ce_window_idx = 2,
.fixed_fw_mem = true,
+ .support_off_channel_tx = false,
},
};
@@ -1620,9 +1627,11 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
ieee80211_stop_queues(ar->hw);
ath11k_mac_drain_tx(ar);
+ ar->state_11d = ATH11K_11D_IDLE;
complete(&ar->completed_11d_scan);
complete(&ar->scan.started);
complete(&ar->scan.completed);
+ complete(&ar->scan.on_channel);
complete(&ar->peer_assoc_done);
complete(&ar->peer_delete_done);
complete(&ar->install_key_done);
@@ -1768,7 +1777,6 @@ static void ath11k_core_reset(struct work_struct *work)
ATH11K_RECOVER_START_TIMEOUT_HZ);
ath11k_hif_power_down(ab);
- ath11k_qmi_free_resource(ab);
ath11k_hif_power_up(ab);
ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 00a45819907e..c17a2620aad7 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -520,6 +520,7 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
struct hal_tx_status *ts)
{
struct ieee80211_tx_status status = { 0 };
+ struct ieee80211_rate_status status_rate = { 0 };
struct ath11k_base *ab = ar->ab;
struct ieee80211_tx_info *info;
struct ath11k_skb_cb *skb_cb;
@@ -603,7 +604,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
status.skb = msdu;
status.info = info;
rate = arsta->last_txrate;
- status.rate = &rate;
+
+ status_rate.rate_idx = rate;
+ status_rate.try_count = 1;
+
+ status.rates = &status_rate;
+ status.n_rates = 1;
spin_unlock_bh(&ab->base_lock);
diff --git a/drivers/net/wireless/ath/ath11k/hal.h b/drivers/net/wireless/ath/ath11k/hal.h
index 1aadb1566df8..110c337ddf33 100644
--- a/drivers/net/wireless/ath/ath11k/hal.h
+++ b/drivers/net/wireless/ath/ath11k/hal.h
@@ -121,7 +121,7 @@ struct ath11k_base;
#define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008
#define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c
#define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010
-#define HAL_REO1_MISC_CTL 0x00000630
+#define HAL_REO1_MISC_CTL(ab) ab->hw_params.regs->hal_reo1_misc_ctl
#define HAL_REO1_RING_BASE_LSB(ab) ab->hw_params.regs->hal_reo1_ring_base_lsb
#define HAL_REO1_RING_BASE_MSB(ab) ab->hw_params.regs->hal_reo1_ring_base_msb
#define HAL_REO1_RING_ID(ab) ab->hw_params.regs->hal_reo1_ring_id
diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
index 09ce357f0f0d..96db85c55585 100644
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -771,10 +771,10 @@ static void ath11k_hw_wcn6855_reo_setup(struct ath11k_base *ab)
FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1);
ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val);
- val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL);
+ val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL(ab));
val &= ~HAL_REO1_MISC_CTL_FRAGMENT_DST_RING;
val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DST_RING, HAL_SRNG_RING_ID_REO2SW1);
- ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL, val);
+ ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL(ab), val);
ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab),
HAL_DEFAULT_REO_TIMEOUT_USEC);
@@ -1983,6 +1983,9 @@ const struct ath11k_hw_regs ipq8074_regs = {
/* Shadow register area */
.hal_shadow_base_addr = 0x0,
+
+ /* REO misc control register, not used in IPQ8074 */
+ .hal_reo1_misc_ctl = 0x0,
};
const struct ath11k_hw_regs qca6390_regs = {
@@ -2065,6 +2068,9 @@ const struct ath11k_hw_regs qca6390_regs = {
/* Shadow register area */
.hal_shadow_base_addr = 0x000008fc,
+
+ /* REO misc control register, not used in QCA6390 */
+ .hal_reo1_misc_ctl = 0x0,
};
const struct ath11k_hw_regs qcn9074_regs = {
@@ -2147,6 +2153,9 @@ const struct ath11k_hw_regs qcn9074_regs = {
/* Shadow register area */
.hal_shadow_base_addr = 0x0,
+
+ /* REO misc control register, not used in QCN9074 */
+ .hal_reo1_misc_ctl = 0x0,
};
const struct ath11k_hw_regs wcn6855_regs = {
@@ -2229,6 +2238,11 @@ const struct ath11k_hw_regs wcn6855_regs = {
/* Shadow register area */
.hal_shadow_base_addr = 0x000008fc,
+
+ /* REO misc control register, used for fragment
+ * destination ring config in WCN6855.
+ */
+ .hal_reo1_misc_ctl = 0x00000630,
};
const struct ath11k_hw_regs wcn6750_regs = {
@@ -2311,6 +2325,11 @@ const struct ath11k_hw_regs wcn6750_regs = {
/* Shadow register area */
.hal_shadow_base_addr = 0x00000504,
+
+ /* REO misc control register, used for fragment
+ * destination ring config in WCN6750.
+ */
+ .hal_reo1_misc_ctl = 0x000005d8,
};
const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = {
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 6d588cd80093..77dc5c851c9b 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -204,6 +204,7 @@ struct ath11k_hw_params {
u8 dp_window_idx;
u8 ce_window_idx;
bool fixed_fw_mem;
+ bool support_off_channel_tx;
};
struct ath11k_hw_ops {
@@ -379,6 +380,7 @@ struct ath11k_hw_regs {
u32 pcie_pcs_osc_dtct_config_base;
u32 hal_shadow_base_addr;
+ u32 hal_reo1_misc_ctl;
};
extern const struct ath11k_hw_regs ipq8074_regs;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 1957e1713548..ee1590b16eff 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1951,7 +1951,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
/* Calculate peer NSS capability from VHT capabilities if STA
* supports VHT.
*/
- for (i = 0, max_nss = 0, vht_mcs = 0; i < NL80211_VHT_NSS_MAX; i++) {
+ for (i = 0, max_nss = 0; i < NL80211_VHT_NSS_MAX; i++) {
vht_mcs = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) >>
(2 * i) & 3;
@@ -2272,7 +2272,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
/* Calculate peer NSS capability from HE capabilities if STA
* supports HE.
*/
- for (i = 0, max_nss = 0, he_mcs = 0; i < NL80211_HE_NSS_MAX; i++) {
+ for (i = 0, max_nss = 0; i < NL80211_HE_NSS_MAX; i++) {
he_mcs = he_tx_mcs >> (2 * i) & 3;
/* In case of fixed rates, MCS Range in he_tx_mcs might have
@@ -5551,8 +5551,8 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
}
arvif = ath11k_vif_to_arvif(skb_cb->vif);
- if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) &&
- arvif->is_started) {
+ mutex_lock(&ar->conf_mutex);
+ if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) {
ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb);
if (ret) {
ath11k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
@@ -5570,6 +5570,7 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
arvif->is_started);
ath11k_mgmt_over_wmi_tx_drop(ar, skb);
}
+ mutex_unlock(&ar->conf_mutex);
}
}
@@ -6155,6 +6156,11 @@ void ath11k_mac_11d_scan_stop(struct ath11k *ar)
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d vdev id %d\n",
ar->vdev_id_11d_scan);
+ if (ar->state_11d == ATH11K_11D_PREPARING) {
+ ar->state_11d = ATH11K_11D_IDLE;
+ complete(&ar->completed_11d_scan);
+ }
+
if (ar->vdev_id_11d_scan != ATH11K_11D_INVALID_VDEV_ID) {
vdev_id = ar->vdev_id_11d_scan;
@@ -7741,6 +7747,7 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b
bool he_fixed_rate = false, vht_fixed_rate = false;
struct ath11k_peer *peer, *tmp;
const u16 *vht_mcs_mask, *he_mcs_mask;
+ struct ieee80211_link_sta *deflink;
u8 vht_nss, he_nss;
bool ret = true;
@@ -7763,13 +7770,16 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b
spin_lock_bh(&ar->ab->base_lock);
list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) {
if (peer->sta) {
- if (vht_fixed_rate && (!peer->sta->deflink.vht_cap.vht_supported ||
- peer->sta->deflink.rx_nss < vht_nss)) {
+ deflink = &peer->sta->deflink;
+
+ if (vht_fixed_rate && (!deflink->vht_cap.vht_supported ||
+ deflink->rx_nss < vht_nss)) {
ret = false;
goto out;
}
- if (he_fixed_rate && (!peer->sta->deflink.he_cap.has_he ||
- peer->sta->deflink.rx_nss < he_nss)) {
+
+ if (he_fixed_rate && (!deflink->he_cap.has_he ||
+ deflink->rx_nss < he_nss)) {
ret = false;
goto out;
}
@@ -8345,6 +8355,118 @@ exit:
return ret;
}
+static int ath11k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ath11k *ar = hw->priv;
+
+ mutex_lock(&ar->conf_mutex);
+
+ spin_lock_bh(&ar->data_lock);
+ ar->scan.roc_notify = false;
+ spin_unlock_bh(&ar->data_lock);
+
+ ath11k_scan_abort(ar);
+
+ mutex_unlock(&ar->conf_mutex);
+
+ cancel_delayed_work_sync(&ar->scan.timeout);
+
+ return 0;
+}
+
+static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan,
+ int duration,
+ enum ieee80211_roc_type type)
+{
+ struct ath11k *ar = hw->priv;
+ struct ath11k_vif *arvif = (void *)vif->drv_priv;
+ struct scan_req_params arg;
+ int ret;
+ u32 scan_time_msec;
+
+ mutex_lock(&ar->conf_mutex);
+
+ spin_lock_bh(&ar->data_lock);
+ switch (ar->scan.state) {
+ case ATH11K_SCAN_IDLE:
+ reinit_completion(&ar->scan.started);
+ reinit_completion(&ar->scan.completed);
+ reinit_completion(&ar->scan.on_channel);
+ ar->scan.state = ATH11K_SCAN_STARTING;
+ ar->scan.is_roc = true;
+ ar->scan.vdev_id = arvif->vdev_id;
+ ar->scan.roc_freq = chan->center_freq;
+ ar->scan.roc_notify = true;
+ ret = 0;
+ break;
+ case ATH11K_SCAN_STARTING:
+ case ATH11K_SCAN_RUNNING:
+ case ATH11K_SCAN_ABORTING:
+ ret = -EBUSY;
+ break;
+ }
+ spin_unlock_bh(&ar->data_lock);
+
+ if (ret)
+ goto exit;
+
+ scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2;
+
+ memset(&arg, 0, sizeof(arg));
+ ath11k_wmi_start_scan_init(ar, &arg);
+ arg.num_chan = 1;
+ arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
+ GFP_KERNEL);
+ if (!arg.chan_list) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ arg.vdev_id = arvif->vdev_id;
+ arg.scan_id = ATH11K_SCAN_ID;
+ arg.chan_list[0] = chan->center_freq;
+ arg.dwell_time_active = scan_time_msec;
+ arg.dwell_time_passive = scan_time_msec;
+ arg.max_scan_time = scan_time_msec;
+ arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE;
+ arg.scan_flags |= WMI_SCAN_FILTER_PROBE_REQ;
+ arg.burst_duration = duration;
+
+ ret = ath11k_start_scan(ar, &arg);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to start roc scan: %d\n", ret);
+
+ spin_lock_bh(&ar->data_lock);
+ ar->scan.state = ATH11K_SCAN_IDLE;
+ spin_unlock_bh(&ar->data_lock);
+ goto free_chan_list;
+ }
+
+ ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ);
+ if (ret == 0) {
+ ath11k_warn(ar->ab, "failed to switch to channel for roc scan\n");
+ ret = ath11k_scan_stop(ar);
+ if (ret)
+ ath11k_warn(ar->ab, "failed to stop scan: %d\n", ret);
+ ret = -ETIMEDOUT;
+ goto free_chan_list;
+ }
+
+ ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
+ msecs_to_jiffies(duration));
+
+ ret = 0;
+
+free_chan_list:
+ kfree(arg.chan_list);
+exit:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
static const struct ieee80211_ops ath11k_ops = {
.tx = ath11k_mac_op_tx,
.start = ath11k_mac_op_start,
@@ -8397,6 +8519,8 @@ static const struct ieee80211_ops ath11k_ops = {
#endif
.set_sar_specs = ath11k_mac_op_set_bios_sar_specs,
+ .remain_on_channel = ath11k_mac_op_remain_on_channel,
+ .cancel_remain_on_channel = ath11k_mac_op_cancel_remain_on_channel,
};
static void ath11k_mac_update_ch_list(struct ath11k *ar,
@@ -8986,6 +9110,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
init_completion(&ar->bss_survey_done);
init_completion(&ar->scan.started);
init_completion(&ar->scan.completed);
+ init_completion(&ar->scan.on_channel);
init_completion(&ar->thermal.wmi_sync);
INIT_DELAYED_WORK(&ar->scan.timeout, ath11k_scan_timeout_work);
@@ -9026,3 +9151,34 @@ void ath11k_mac_destroy(struct ath11k_base *ab)
pdev->ar = NULL;
}
}
+
+int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,
+ enum wmi_sta_keepalive_method method,
+ u32 interval)
+{
+ struct ath11k *ar = arvif->ar;
+ struct wmi_sta_keepalive_arg arg = {};
+ int ret;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ return 0;
+
+ if (!test_bit(WMI_TLV_SERVICE_STA_KEEP_ALIVE, ar->ab->wmi_ab.svc_map))
+ return 0;
+
+ arg.vdev_id = arvif->vdev_id;
+ arg.enabled = 1;
+ arg.method = method;
+ arg.interval = interval;
+
+ ret = ath11k_wmi_sta_keepalive(ar, &arg);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to set keepalive on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
index 7f93e3a9ca23..57ebfc592b00 100644
--- a/drivers/net/wireless/ath/ath11k/mac.h
+++ b/drivers/net/wireless/ath/ath11k/mac.h
@@ -8,6 +8,7 @@
#include <net/mac80211.h>
#include <net/cfg80211.h>
+#include "wmi.h"
struct ath11k;
struct ath11k_base;
@@ -173,4 +174,7 @@ void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb);
void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id);
void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif);
int ath11k_mac_wait_tx_complete(struct ath11k *ar);
+int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,
+ enum wmi_sta_keepalive_method method,
+ u32 interval);
#endif
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index d1e945074bc1..61ead37a944a 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -1970,6 +1970,21 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
chunk = &ab->qmi.target_mem[i];
+
+ /* Firmware reloads in coldboot/firmware recovery.
+ * in such case, no need to allocate memory for FW again.
+ */
+ if (chunk->vaddr) {
+ if (chunk->prev_type == chunk->type ||
+ chunk->prev_size == chunk->size)
+ continue;
+
+ /* cannot reuse the existing chunk */
+ dma_free_coherent(ab->dev, chunk->size,
+ chunk->vaddr, chunk->paddr);
+ chunk->vaddr = NULL;
+ }
+
chunk->vaddr = dma_alloc_coherent(ab->dev,
chunk->size,
&chunk->paddr,
@@ -1990,6 +2005,8 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
chunk->type);
return -EINVAL;
}
+ chunk->prev_type = chunk->type;
+ chunk->prev_size = chunk->size;
}
return 0;
@@ -2466,9 +2483,6 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
char path[100];
int ret;
- if (m3_mem->vaddr || m3_mem->size)
- return 0;
-
fw = ath11k_core_firmware_request(ab, ATH11K_M3_FILE);
if (IS_ERR(fw)) {
ret = PTR_ERR(fw);
@@ -2478,6 +2492,9 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
return ret;
}
+ if (m3_mem->vaddr || m3_mem->size)
+ goto skip_m3_alloc;
+
m3_mem->vaddr = dma_alloc_coherent(ab->dev,
fw->size, &m3_mem->paddr,
GFP_KERNEL);
@@ -2488,6 +2505,7 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
return -ENOMEM;
}
+skip_m3_alloc:
memcpy(m3_mem->vaddr, fw->data, fw->size);
m3_mem->size = fw->size;
release_firmware(fw);
diff --git a/drivers/net/wireless/ath/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h
index c24e6995cca3..c83cf822be81 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.h
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
@@ -97,6 +97,8 @@ struct ath11k_qmi_event_msg {
struct target_mem_chunk {
u32 size;
u32 type;
+ u32 prev_size;
+ u32 prev_type;
dma_addr_t paddr;
u32 *vaddr;
void __iomem *iaddr;
diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index 79ac2142317a..7ee3ff69dfc8 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -139,6 +139,9 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
"reg hw scan wait left time %d\n", left);
}
+ if (ar->state == ATH11K_STATE_RESTARTING)
+ return 0;
+
bands = hw->wiphy->bands;
for (band = 0; band < NUM_NL80211_BANDS; band++) {
if (!bands[band])
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 1410114d1d5c..84d1c7054013 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -625,10 +625,25 @@ struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len)
return skb;
}
+static u32 ath11k_wmi_mgmt_get_freq(struct ath11k *ar,
+ struct ieee80211_tx_info *info)
+{
+ struct ath11k_base *ab = ar->ab;
+ u32 freq = 0;
+
+ if (ab->hw_params.support_off_channel_tx &&
+ ar->scan.is_roc &&
+ (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN))
+ freq = ar->scan.roc_freq;
+
+ return freq;
+}
+
int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
struct sk_buff *frame)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame);
struct wmi_mgmt_send_cmd *cmd;
struct wmi_tlv *frame_tlv;
struct sk_buff *skb;
@@ -649,7 +664,7 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->vdev_id = vdev_id;
cmd->desc_id = buf_id;
- cmd->chanfreq = 0;
+ cmd->chanfreq = ath11k_wmi_mgmt_get_freq(ar, info);
cmd->paddr_lo = lower_32_bits(ATH11K_SKB_CB(frame)->paddr);
cmd->paddr_hi = upper_32_bits(ATH11K_SKB_CB(frame)->paddr);
cmd->frame_len = frame->len;
@@ -5264,6 +5279,8 @@ static void ath11k_wmi_event_scan_started(struct ath11k *ar)
break;
case ATH11K_SCAN_STARTING:
ar->scan.state = ATH11K_SCAN_RUNNING;
+ if (ar->scan.is_roc)
+ ieee80211_ready_on_channel(ar->hw);
complete(&ar->scan.started);
break;
}
@@ -5346,6 +5363,8 @@ static void ath11k_wmi_event_scan_foreign_chan(struct ath11k *ar, u32 freq)
case ATH11K_SCAN_RUNNING:
case ATH11K_SCAN_ABORTING:
ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq);
+ if (ar->scan.is_roc && ar->scan.roc_freq == freq)
+ complete(&ar->scan.on_channel);
break;
}
}
@@ -8959,3 +8978,44 @@ int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar)
return ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID);
}
+
+int ath11k_wmi_sta_keepalive(struct ath11k *ar,
+ const struct wmi_sta_keepalive_arg *arg)
+{
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
+ struct wmi_sta_keepalive_cmd *cmd;
+ struct wmi_sta_keepalive_arp_resp *arp;
+ struct sk_buff *skb;
+ size_t len;
+
+ len = sizeof(*cmd) + sizeof(*arp);
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_sta_keepalive_cmd *)skb->data;
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
+ WMI_TAG_STA_KEEPALIVE_CMD) |
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+ cmd->vdev_id = arg->vdev_id;
+ cmd->enabled = arg->enabled;
+ cmd->interval = arg->interval;
+ cmd->method = arg->method;
+
+ if (arg->method == WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE ||
+ arg->method == WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST) {
+ arp = (struct wmi_sta_keepalive_arp_resp *)(cmd + 1);
+ arp->tlv_header = FIELD_PREP(WMI_TLV_TAG,
+ WMI_TAG_STA_KEEPALVE_ARP_RESPONSE) |
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*arp) - TLV_HDR_SIZE);
+ arp->src_ip4_addr = arg->src_ip4_addr;
+ arp->dest_ip4_addr = arg->dest_ip4_addr;
+ ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
+ }
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "wmi sta keepalive vdev %d enabled %d method %d interval %d\n",
+ arg->vdev_id, arg->enabled, arg->method, arg->interval);
+
+ return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
+}
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 7600e9a52da8..b1fad4707dc6 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -5907,6 +5907,50 @@ struct wmi_pdev_set_geo_table_cmd {
u32 rsvd_len;
} __packed;
+struct wmi_sta_keepalive_cmd {
+ u32 tlv_header;
+ u32 vdev_id;
+ u32 enabled;
+
+ /* WMI_STA_KEEPALIVE_METHOD_ */
+ u32 method;
+
+ /* in seconds */
+ u32 interval;
+
+ /* following this structure is the TLV for struct
+ * wmi_sta_keepalive_arp_resp
+ */
+} __packed;
+
+struct wmi_sta_keepalive_arp_resp {
+ u32 tlv_header;
+ u32 src_ip4_addr;
+ u32 dest_ip4_addr;
+ struct wmi_mac_addr dest_mac_addr;
+} __packed;
+
+struct wmi_sta_keepalive_arg {
+ u32 vdev_id;
+ u32 enabled;
+ u32 method;
+ u32 interval;
+ u32 src_ip4_addr;
+ u32 dest_ip4_addr;
+ const u8 dest_mac_addr[ETH_ALEN];
+};
+
+enum wmi_sta_keepalive_method {
+ WMI_STA_KEEPALIVE_METHOD_NULL_FRAME = 1,
+ WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE = 2,
+ WMI_STA_KEEPALIVE_METHOD_ETHERNET_LOOPBACK = 3,
+ WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST = 4,
+ WMI_STA_KEEPALIVE_METHOD_MGMT_VENDOR_ACTION = 5,
+};
+
+#define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30
+#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0
+
int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
u32 cmd_id);
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len);
@@ -6087,5 +6131,7 @@ int ath11k_wmi_gtk_rekey_getinfo(struct ath11k *ar,
struct ath11k_vif *arvif);
int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_val);
int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar);
+int ath11k_wmi_sta_keepalive(struct ath11k *ar,
+ const struct wmi_sta_keepalive_arg *arg);
#endif
diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c
index 9d088cebef03..b3e65cd13d83 100644
--- a/drivers/net/wireless/ath/ath11k/wow.c
+++ b/drivers/net/wireless/ath/ath11k/wow.c
@@ -640,6 +640,24 @@ static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable)
return 0;
}
+static int ath11k_wow_set_keepalive(struct ath11k *ar,
+ enum wmi_sta_keepalive_method method,
+ u32 interval)
+{
+ struct ath11k_vif *arvif;
+ int ret;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ list_for_each_entry(arvif, &ar->arvifs, list) {
+ ret = ath11k_mac_vif_set_keepalive(arvif, method, interval);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
int ath11k_wow_op_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
{
@@ -691,6 +709,14 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw,
goto cleanup;
}
+ ret = ath11k_wow_set_keepalive(ar,
+ WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
+ WMI_STA_KEEPALIVE_INTERVAL_DEFAULT);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to enable wow keepalive: %d\n", ret);
+ goto cleanup;
+ }
+
ret = ath11k_wow_enable(ar->ab);
if (ret) {
ath11k_warn(ar->ab, "failed to start wow: %d\n", ret);
@@ -786,6 +812,14 @@ int ath11k_wow_op_resume(struct ieee80211_hw *hw)
goto exit;
}
+ ret = ath11k_wow_set_keepalive(ar,
+ WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
+ WMI_STA_KEEPALIVE_INTERVAL_DISABLE);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to disable wow keepalive: %d\n", ret);
+ goto exit;
+ }
+
exit:
if (ret) {
switch (ar->state) {
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 4c944e595978..64d6c98174c8 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1391,19 +1391,6 @@ static int temp_show(struct seq_file *s, void *data)
}
DEFINE_SHOW_ATTRIBUTE(temp);
-/*---------freq------------*/
-static int freq_show(struct seq_file *s, void *data)
-{
- struct wil6210_priv *wil = s->private;
- struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
- u32 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
-
- seq_printf(s, "Freq = %d\n", freq);
-
- return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(freq);
-
/*---------link------------*/
static int link_show(struct seq_file *s, void *data)
{
@@ -2380,7 +2367,6 @@ static const struct {
{"pmcdata", 0444, &fops_pmcdata},
{"pmcring", 0444, &fops_pmcring},
{"temp", 0444, &temp_fops},
- {"freq", 0444, &freq_fops},
{"link", 0444, &link_fops},
{"info", 0444, &info_fops},
{"recovery", 0644, &fops_recovery},
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 390648066382..87a88f26233e 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -458,16 +458,14 @@ int wil_if_add(struct wil6210_priv *wil)
netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
wil6210_netdev_poll_rx_edma,
NAPI_POLL_WEIGHT);
- netif_tx_napi_add(&wil->napi_ndev,
- &wil->napi_tx, wil6210_netdev_poll_tx_edma,
- NAPI_POLL_WEIGHT);
+ netif_napi_add_tx(&wil->napi_ndev,
+ &wil->napi_tx, wil6210_netdev_poll_tx_edma);
} else {
netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
wil6210_netdev_poll_rx,
NAPI_POLL_WEIGHT);
- netif_tx_napi_add(&wil->napi_ndev,
- &wil->napi_tx, wil6210_netdev_poll_tx,
- NAPI_POLL_WEIGHT);
+ netif_napi_add_tx(&wil->napi_ndev,
+ &wil->napi_tx, wil6210_netdev_poll_tx);
}
wil_update_net_queues_bh(wil, vif, NULL, true);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index e3758bd86acf..fe01da9e620d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -202,13 +202,24 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
char *ptr;
s32 err;
- /* retreive mac address */
- err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
- sizeof(ifp->mac_addr));
- if (err < 0) {
- bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err);
- goto done;
+ if (is_valid_ether_addr(ifp->mac_addr)) {
+ /* set mac address */
+ err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
+ ETH_ALEN);
+ if (err < 0) {
+ bphy_err(ifp->drvr, "Setting cur_etheraddr failed, %d\n", err);
+ goto done;
+ }
+ } else {
+ /* retrieve mac address */
+ err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
+ sizeof(ifp->mac_addr));
+ if (err < 0) {
+ bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err);
+ goto done;
+ }
}
+
memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
index 8b5f49997c8b..15accc88d5c0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -50,6 +50,7 @@ struct brcmf_mp_device {
bool ignore_probe_fail;
struct brcmfmac_pd_cc *country_codes;
const char *board_type;
+ unsigned char mac[ETH_ALEN];
union {
struct brcmfmac_sdio_pd sdio;
} bus;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 26fab4bee22c..87aef211b35f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -7,6 +7,7 @@
#include <linux/etherdevice.h>
#include <linux/module.h>
#include <linux/inetdevice.h>
+#include <linux/property.h>
#include <net/cfg80211.h>
#include <net/rtnetlink.h>
#include <net/addrconf.h>
@@ -1197,7 +1198,8 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
brcmf_dbg(TRACE, "\n");
/* add primary networking interface */
- ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL);
+ ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d",
+ is_valid_ether_addr(drvr->settings->mac) ? drvr->settings->mac : NULL);
if (IS_ERR(ifp))
return PTR_ERR(ifp);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
index 8623bde5eb70..083ac58f466d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
@@ -5,6 +5,7 @@
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_irq.h>
+#include <linux/of_net.h>
#include <defs.h>
#include "debug.h"
@@ -99,6 +100,8 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
if (err)
brcmf_err("failed to get OF country code map (err=%d)\n", err);
+ of_get_mac_address(np, settings->mac);
+
if (bus_type != BRCMF_BUSTYPE_SDIO)
return;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index 33aae639ad37..e6d64152c81a 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -937,6 +937,9 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
{
int i, j;
+ if (!fwrt->geo_enabled)
+ return -ENODATA;
+
if (!iwl_sar_geo_support(fwrt))
return -EOPNOTSUPP;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index a22788a68168..157d1f31c487 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -389,6 +389,8 @@ enum {
#define WFPM_LMAC1_PD_NOTIFICATION 0xa0338c
#define WFPM_ARC1_PD_NOTIFICATION 0xa03044
#define HPM_SECONDARY_DEVICE_STATE 0xa03404
+#define WFPM_MAC_OTP_CFG7_ADDR 0xa03338
+#define WFPM_MAC_OTP_CFG7_DATA 0xa0333c
/* For UMAG_GEN_HW_STATUS reg check */
diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c
index b4f45234cfc8..357f14626cf4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mei/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c
@@ -493,6 +493,7 @@ void iwl_mei_add_data_to_ring(struct sk_buff *skb, bool cb_tx)
if (cb_tx) {
struct iwl_sap_cb_data *cb_hdr = skb_push(skb, sizeof(*cb_hdr));
+ memset(cb_hdr, 0, sizeof(*cb_hdr));
cb_hdr->hdr.type = cpu_to_le16(SAP_MSG_CB_DATA_PACKET);
cb_hdr->hdr.len = cpu_to_le16(skb->len - sizeof(cb_hdr->hdr));
cb_hdr->hdr.seq_num = cpu_to_le32(atomic_inc_return(&mei->sap_seq_no));
@@ -1019,6 +1020,8 @@ static void iwl_mei_handle_sap_data(struct mei_cl_device *cldev,
/* We need enough room for the WiFi header + SNAP + IV */
skb = netdev_alloc_skb(netdev, len + QOS_HDR_IV_SNAP_LEN);
+ if (!skb)
+ continue;
skb_reserve(skb, QOS_HDR_IV_SNAP_LEN);
ethhdr = skb_push(skb, sizeof(*ethhdr));
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index bcc4ed20fe5b..61f9136a333d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -1956,18 +1956,18 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \
\
if (len < sizeof(*data)) { \
IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); \
- return ERR_PTR(-EIO); \
+ return NULL; \
} \
\
data_size = ALIGN(le32_to_cpu(data->wake_packet_bufsize), 4); \
if (len != sizeof(*data) + data_size) { \
IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); \
- return ERR_PTR(-EIO); \
+ return NULL; \
} \
\
status = kzalloc(sizeof(*status) + data_size, GFP_KERNEL); \
if (!status) \
- return ERR_PTR(-ENOMEM); \
+ return NULL; \
\
/* copy all the common fields */ \
status->replay_ctr = le64_to_cpu(data->replay_ctr); \
@@ -2097,7 +2097,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data;
status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len);
- if (IS_ERR(status))
+ if (!status)
goto out_free_resp;
BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) >
@@ -2128,7 +2128,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
status = iwl_mvm_parse_wowlan_status_common_v7(mvm, v7, len);
- if (IS_ERR(status))
+ if (!status)
goto out_free_resp;
iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc);
@@ -2141,7 +2141,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
* difference is only in a few not used (reserved) fields.
*/
status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len);
- if (IS_ERR(status))
+ if (!status)
goto out_free_resp;
iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc);
@@ -2153,7 +2153,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data;
status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len);
- if (IS_ERR(status))
+ if (!status)
goto out_free_resp;
iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc);
@@ -2165,7 +2165,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
IWL_ERR(mvm,
"Firmware advertises unknown WoWLAN status response %d!\n",
notif_ver);
- status = ERR_PTR(-EIO);
+ status = NULL;
}
out_free_resp:
@@ -2203,7 +2203,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_ap_sta;
status = iwl_mvm_get_wakeup_status(mvm, mvmvif->ap_sta_id);
- if (IS_ERR(status))
+ if (!status)
goto out_unlock;
IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n",
@@ -2370,7 +2370,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
int i, n_matches, ret;
status = iwl_mvm_get_wakeup_status(mvm, IWL_MVM_INVALID_STA);
- if (!IS_ERR(status)) {
+ if (status) {
reasons = status->wakeup_reasons;
kfree(status);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index e842816134f1..f041e77af059 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -287,6 +287,9 @@ static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
static void iwl_mvm_print_pd_notification(struct iwl_mvm *mvm)
{
+#define IWL_FW_PRINT_REG_INFO(reg_name) \
+ IWL_ERR(mvm, #reg_name ": 0x%x\n", iwl_read_umac_prph(trans, reg_name))
+
struct iwl_trans *trans = mvm->trans;
enum iwl_device_family device_family = trans->trans_cfg->device_family;
@@ -294,15 +297,15 @@ static void iwl_mvm_print_pd_notification(struct iwl_mvm *mvm)
return;
if (device_family <= IWL_DEVICE_FAMILY_9000)
- IWL_ERR(mvm, "WFPM_ARC1_PD_NOTIFICATION: 0x%x\n",
- iwl_read_umac_prph(trans, WFPM_ARC1_PD_NOTIFICATION));
+ IWL_FW_PRINT_REG_INFO(WFPM_ARC1_PD_NOTIFICATION);
else
- IWL_ERR(mvm, "WFPM_LMAC1_PD_NOTIFICATION: 0x%x\n",
- iwl_read_umac_prph(trans, WFPM_LMAC1_PD_NOTIFICATION));
+ IWL_FW_PRINT_REG_INFO(WFPM_LMAC1_PD_NOTIFICATION);
- IWL_ERR(mvm, "HPM_SECONDARY_DEVICE_STATE: 0x%x\n",
- iwl_read_umac_prph(trans, HPM_SECONDARY_DEVICE_STATE));
+ IWL_FW_PRINT_REG_INFO(HPM_SECONDARY_DEVICE_STATE);
+ /* print OPT info */
+ IWL_FW_PRINT_REG_INFO(WFPM_MAC_OTP_CFG7_ADDR);
+ IWL_FW_PRINT_REG_INFO(WFPM_MAC_OTP_CFG7_DATA);
}
static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 5aa4520b70ac..56fa20596f16 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -552,6 +552,12 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, bssid_override, action);
+ /*
+ * We always want to hear MCAST frames, if we're not authorized yet,
+ * we'll drop them.
+ */
+ cmd.filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
+
if (vif->p2p) {
struct ieee80211_p2p_noa_attr *noa =
&vif->bss_conf.p2p_noa_attr;
@@ -567,7 +573,6 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
!force_assoc_off) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u8 ap_sta_id = mvmvif->ap_sta_id;
u32 dtim_offs;
/*
@@ -609,29 +614,6 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))
ctxt_sta->data_policy |=
cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE);
-
- /*
- * allow multicast data frames only as long as the station is
- * authorized, i.e., GTK keys are already installed (if needed)
- */
- if (ap_sta_id < mvm->fw->ucode_capa.num_stations) {
- struct ieee80211_sta *sta;
-
- rcu_read_lock();
-
- sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
- if (!IS_ERR_OR_NULL(sta)) {
- struct iwl_mvm_sta *mvmsta =
- iwl_mvm_sta_from_mac80211(sta);
-
- if (mvmsta->sta_state ==
- IEEE80211_STA_AUTHORIZED)
- cmd.filter_flags |=
- cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
- }
-
- rcu_read_unlock();
- }
} else {
ctxt_sta->is_assoc = cpu_to_le32(0);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 4fda6c3ba9f3..bb9bd2165355 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -976,7 +976,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
ieee80211_wake_queues(mvm->hw);
- mvm->vif_count = 0;
mvm->rx_ba_sessions = 0;
mvm->fwrt.dump.conf = FW_DBG_INVALID;
mvm->monitor_on = false;
@@ -1380,10 +1379,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
- /* Counting number of interfaces is needed for legacy PM */
- if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
- mvm->vif_count++;
-
/*
* The AP binding flow can be done only after the beacon
* template is configured (which happens only in the mac80211
@@ -1400,7 +1395,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
ret = iwl_mvm_alloc_bcast_sta(mvm, vif);
if (ret) {
IWL_ERR(mvm, "Failed to allocate bcast sta\n");
- goto out_release;
+ goto out_unlock;
}
/*
@@ -1411,7 +1406,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
0, vif->type,
IWL_STA_MULTICAST);
if (ret)
- goto out_release;
+ goto out_unlock;
iwl_mvm_vif_dbgfs_register(mvm, vif);
goto out_unlock;
@@ -1421,7 +1416,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
ret = iwl_mvm_mac_ctxt_add(mvm, vif);
if (ret)
- goto out_release;
+ goto out_unlock;
ret = iwl_mvm_power_update_mac(mvm);
if (ret)
@@ -1498,9 +1493,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
out_remove_mac:
mvmvif->phy_ctxt = NULL;
iwl_mvm_mac_ctxt_remove(mvm, vif);
- out_release:
- if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
- mvm->vif_count--;
out_unlock:
mutex_unlock(&mvm->mutex);
@@ -1582,9 +1574,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mvmvif->phy_ctxt = NULL;
}
- if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)
- mvm->vif_count--;
-
iwl_mvm_power_update_mac(mvm);
iwl_mvm_mac_ctxt_remove(mvm, vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index c6bc85d4600a..bf35e130c876 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -934,7 +934,6 @@ struct iwl_mvm {
unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
u8 fw_key_deleted[STA_KEY_MAX_NUM];
- u8 vif_count;
struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
/* -1 for always, 0 for never, >0 for that many times */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index b2ea2fca5376..b9bd81242b21 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -563,6 +563,9 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
struct iwl_power_vifs *power_iterator = _data;
bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX;
+ if (!mvmvif->uploaded)
+ return;
+
switch (ieee80211_vif_type_p2p(vif)) {
case NL80211_IFTYPE_P2P_DEVICE:
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 78198da7e55b..49ca1e168fc5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -327,17 +327,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
rx_status = IEEE80211_SKB_RXCB(skb);
/*
- * drop the packet if it has failed being decrypted by HW
- */
- if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status,
- &crypt_len)) {
- IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n",
- rx_pkt_status);
- kfree_skb(skb);
- return;
- }
-
- /*
* Keep packets with CRC errors (and with overrun) for monitor mode
* (otherwise the firmware discards them) but mark them as bad.
*/
@@ -388,6 +377,37 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
if (sta) {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ struct ieee80211_vif *vif = mvmsta->vif;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ /*
+ * Don't even try to decrypt a MCAST frame that was received
+ * before the managed vif is authorized, we'd fail anyway.
+ */
+ if (vif->type == NL80211_IFTYPE_STATION &&
+ !mvmvif->authorized &&
+ is_multicast_ether_addr(hdr->addr1)) {
+ IWL_DEBUG_DROP(mvm, "MCAST before the vif is authorized\n");
+ kfree_skb(skb);
+ rcu_read_unlock();
+ return;
+ }
+ }
+
+ /*
+ * drop the packet if it has failed being decrypted by HW
+ */
+ if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status,
+ &crypt_len)) {
+ IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n",
+ rx_pkt_status);
+ kfree_skb(skb);
+ rcu_read_unlock();
+ return;
+ }
+
+ if (sta) {
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct ieee80211_vif *tx_blocked_vif =
rcu_dereference(mvm->csa_tx_blocked_vif);
struct iwl_fw_dbg_trigger_tlv *trig;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 8be3c3c8c68b..6fc69c42f36e 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1085,34 +1085,44 @@ bool iwl_pcie_check_hw_rf_kill(struct iwl_trans *trans)
}
struct iwl_causes_list {
- u32 cause_num;
- u32 mask_reg;
+ u16 mask_reg;
+ u8 bit;
u8 addr;
};
+#define CAUSE(reg, mask) \
+ { \
+ .mask_reg = reg, \
+ .bit = ilog2(mask), \
+ .addr = ilog2(mask) + \
+ ((reg) == CSR_MSIX_FH_INT_MASK_AD ? -16 : \
+ (reg) == CSR_MSIX_HW_INT_MASK_AD ? 16 : \
+ 0xffff), /* causes overflow warning */ \
+ }
+
static const struct iwl_causes_list causes_list_common[] = {
- {MSIX_FH_INT_CAUSES_D2S_CH0_NUM, CSR_MSIX_FH_INT_MASK_AD, 0},
- {MSIX_FH_INT_CAUSES_D2S_CH1_NUM, CSR_MSIX_FH_INT_MASK_AD, 0x1},
- {MSIX_FH_INT_CAUSES_S2D, CSR_MSIX_FH_INT_MASK_AD, 0x3},
- {MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5},
- {MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10},
- {MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11},
- {MSIX_HW_INT_CAUSES_REG_RESET_DONE, CSR_MSIX_HW_INT_MASK_AD, 0x12},
- {MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16},
- {MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17},
- {MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18},
- {MSIX_HW_INT_CAUSES_REG_SCD, CSR_MSIX_HW_INT_MASK_AD, 0x2A},
- {MSIX_HW_INT_CAUSES_REG_FH_TX, CSR_MSIX_HW_INT_MASK_AD, 0x2B},
- {MSIX_HW_INT_CAUSES_REG_HW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x2D},
- {MSIX_HW_INT_CAUSES_REG_HAP, CSR_MSIX_HW_INT_MASK_AD, 0x2E},
+ CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH0_NUM),
+ CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH1_NUM),
+ CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_S2D),
+ CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_FH_ERR),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_ALIVE),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_WAKEUP),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RESET_DONE),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_CT_KILL),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RF_KILL),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_PERIODIC),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SCD),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_FH_TX),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HW_ERR),
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HAP),
};
static const struct iwl_causes_list causes_list_pre_bz[] = {
- {MSIX_HW_INT_CAUSES_REG_SW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x29},
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR),
};
static const struct iwl_causes_list causes_list_bz[] = {
- {MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ, CSR_MSIX_HW_INT_MASK_AD, 0x15},
+ CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ),
};
static void iwl_pcie_map_list(struct iwl_trans *trans,
@@ -1124,7 +1134,7 @@ static void iwl_pcie_map_list(struct iwl_trans *trans,
for (i = 0; i < arr_size; i++) {
iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
iwl_clear_bit(trans, causes[i].mask_reg,
- causes[i].cause_num);
+ BIT(causes[i].bit));
}
}
diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c
index 72622220051b..10cbd9e560e7 100644
--- a/drivers/net/wireless/mediatek/mt76/agg-rx.c
+++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c
@@ -162,15 +162,15 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
if (!sta)
return;
- if (!status->aggr && !(status->flag & RX_FLAG_8023)) {
- mt76_rx_aggr_check_ctl(skb, frames);
+ if (!status->aggr) {
+ if (!(status->flag & RX_FLAG_8023))
+ mt76_rx_aggr_check_ctl(skb, frames);
return;
}
/* not part of a BA session */
ackp = status->qos_ctl & IEEE80211_QOS_CTL_ACK_POLICY_MASK;
- if (ackp != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK &&
- ackp != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
+ if (ackp == IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
return;
tid = rcu_dereference(wcid->aggr[tidno]);
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index 02daeefb0761..30de8be4aac1 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -7,6 +7,37 @@
#include "mt76.h"
#include "dma.h"
+#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
+
+#define Q_READ(_dev, _q, _field) ({ \
+ u32 _offset = offsetof(struct mt76_queue_regs, _field); \
+ u32 _val; \
+ if ((_q)->flags & MT_QFLAG_WED) \
+ _val = mtk_wed_device_reg_read(&(_dev)->mmio.wed, \
+ ((_q)->wed_regs + \
+ _offset)); \
+ else \
+ _val = readl(&(_q)->regs->_field); \
+ _val; \
+})
+
+#define Q_WRITE(_dev, _q, _field, _val) do { \
+ u32 _offset = offsetof(struct mt76_queue_regs, _field); \
+ if ((_q)->flags & MT_QFLAG_WED) \
+ mtk_wed_device_reg_write(&(_dev)->mmio.wed, \
+ ((_q)->wed_regs + _offset), \
+ _val); \
+ else \
+ writel(_val, &(_q)->regs->_field); \
+} while (0)
+
+#else
+
+#define Q_READ(_dev, _q, _field) readl(&(_q)->regs->_field)
+#define Q_WRITE(_dev, _q, _field, _val) writel(_val, &(_q)->regs->_field)
+
+#endif
+
static struct mt76_txwi_cache *
mt76_alloc_txwi(struct mt76_dev *dev)
{
@@ -16,11 +47,11 @@ mt76_alloc_txwi(struct mt76_dev *dev)
int size;
size = L1_CACHE_ALIGN(dev->drv->txwi_size + sizeof(*t));
- txwi = devm_kzalloc(dev->dev, size, GFP_ATOMIC);
+ txwi = kzalloc(size, GFP_ATOMIC);
if (!txwi)
return NULL;
- addr = dma_map_single(dev->dev, txwi, dev->drv->txwi_size,
+ addr = dma_map_single(dev->dma_dev, txwi, dev->drv->txwi_size,
DMA_TO_DEVICE);
t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size);
t->dma_addr = addr;
@@ -73,18 +104,20 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
struct mt76_txwi_cache *t;
local_bh_disable();
- while ((t = __mt76_get_txwi(dev)) != NULL)
- dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size,
+ while ((t = __mt76_get_txwi(dev)) != NULL) {
+ dma_unmap_single(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
DMA_TO_DEVICE);
+ kfree(mt76_get_txwi_ptr(dev, t));
+ }
local_bh_enable();
}
static void
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
{
- writel(q->desc_dma, &q->regs->desc_base);
- writel(q->ndesc, &q->regs->ring_size);
- q->head = readl(&q->regs->dma_idx);
+ Q_WRITE(dev, q, desc_base, q->desc_dma);
+ Q_WRITE(dev, q, ring_size, q->ndesc);
+ q->head = Q_READ(dev, q, dma_idx);
q->tail = q->head;
}
@@ -100,42 +133,12 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
for (i = 0; i < q->ndesc; i++)
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
- writel(0, &q->regs->cpu_idx);
- writel(0, &q->regs->dma_idx);
+ Q_WRITE(dev, q, cpu_idx, 0);
+ Q_WRITE(dev, q, dma_idx, 0);
mt76_dma_sync_idx(dev, q);
}
static int
-mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
- int idx, int n_desc, int bufsize,
- u32 ring_base)
-{
- int size;
-
- spin_lock_init(&q->lock);
- spin_lock_init(&q->cleanup_lock);
-
- q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE;
- q->ndesc = n_desc;
- q->buf_size = bufsize;
- q->hw_idx = idx;
-
- size = q->ndesc * sizeof(struct mt76_desc);
- q->desc = dmam_alloc_coherent(dev->dev, size, &q->desc_dma, GFP_KERNEL);
- if (!q->desc)
- return -ENOMEM;
-
- size = q->ndesc * sizeof(*q->entry);
- q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
- if (!q->entry)
- return -ENOMEM;
-
- mt76_dma_queue_reset(dev, q);
-
- return 0;
-}
-
-static int
mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76_queue_buf *buf, int nbufs, u32 info,
struct sk_buff *skb, void *txwi)
@@ -203,11 +206,11 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
struct mt76_queue_entry *e = &q->entry[idx];
if (!e->skip_buf0)
- dma_unmap_single(dev->dev, e->dma_addr[0], e->dma_len[0],
+ dma_unmap_single(dev->dma_dev, e->dma_addr[0], e->dma_len[0],
DMA_TO_DEVICE);
if (!e->skip_buf1)
- dma_unmap_single(dev->dev, e->dma_addr[1], e->dma_len[1],
+ dma_unmap_single(dev->dma_dev, e->dma_addr[1], e->dma_len[1],
DMA_TO_DEVICE);
if (e->txwi == DMA_DUMMY_DATA)
@@ -224,7 +227,7 @@ static void
mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
{
wmb();
- writel(q->head, &q->regs->cpu_idx);
+ Q_WRITE(dev, q, cpu_idx, q->head);
}
static void
@@ -240,7 +243,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
if (flush)
last = -1;
else
- last = readl(&q->regs->dma_idx);
+ last = Q_READ(dev, q, dma_idx);
while (q->queued > 0 && q->tail != last) {
mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry);
@@ -252,8 +255,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
}
if (!flush && q->tail == last)
- last = readl(&q->regs->dma_idx);
-
+ last = Q_READ(dev, q, dma_idx);
}
spin_unlock_bh(&q->cleanup_lock);
@@ -288,7 +290,7 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
if (info)
*info = le32_to_cpu(desc->info);
- dma_unmap_single(dev->dev, buf_addr, buf_len, DMA_FROM_DEVICE);
+ dma_unmap_single(dev->dma_dev, buf_addr, buf_len, DMA_FROM_DEVICE);
e->buf = NULL;
return buf;
@@ -325,9 +327,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
if (q->queued + 1 >= q->ndesc - 1)
goto error;
- addr = dma_map_single(dev->dev, skb->data, skb->len,
+ addr = dma_map_single(dev->dma_dev, skb->data, skb->len,
DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(dev->dev, addr)))
+ if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
goto error;
buf.addr = addr;
@@ -374,8 +376,8 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
mt76_insert_hdr_pad(skb);
len = skb_headlen(skb);
- addr = dma_map_single(dev->dev, skb->data, len, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(dev->dev, addr)))
+ addr = dma_map_single(dev->dma_dev, skb->data, len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
goto free;
tx_info.buf[n].addr = t->dma_addr;
@@ -387,9 +389,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
if (n == ARRAY_SIZE(tx_info.buf))
goto unmap;
- addr = dma_map_single(dev->dev, iter->data, iter->len,
+ addr = dma_map_single(dev->dma_dev, iter->data, iter->len,
DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(dev->dev, addr)))
+ if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
goto unmap;
tx_info.buf[n].addr = addr;
@@ -402,10 +404,10 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
goto unmap;
}
- dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size,
+ dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
DMA_TO_DEVICE);
ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info);
- dma_sync_single_for_device(dev->dev, t->dma_addr, dev->drv->txwi_size,
+ dma_sync_single_for_device(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
DMA_TO_DEVICE);
if (ret < 0)
goto unmap;
@@ -415,7 +417,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
unmap:
for (n--; n > 0; n--)
- dma_unmap_single(dev->dev, tx_info.buf[n].addr,
+ dma_unmap_single(dev->dma_dev, tx_info.buf[n].addr,
tx_info.buf[n].len, DMA_TO_DEVICE);
free:
@@ -460,8 +462,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
if (!buf)
break;
- addr = dma_map_single(dev->dev, buf, len, DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(dev->dev, addr))) {
+ addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
skb_free_frag(buf);
break;
}
@@ -481,6 +483,85 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
return frames;
}
+static int
+mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
+{
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ struct mtk_wed_device *wed = &dev->mmio.wed;
+ int ret, type, ring;
+ u8 flags = q->flags;
+
+ if (!mtk_wed_device_active(wed))
+ q->flags &= ~MT_QFLAG_WED;
+
+ if (!(q->flags & MT_QFLAG_WED))
+ return 0;
+
+ type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
+ ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags);
+
+ switch (type) {
+ case MT76_WED_Q_TX:
+ ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs);
+ if (!ret)
+ q->wed_regs = wed->tx_ring[ring].reg_base;
+ break;
+ case MT76_WED_Q_TXFREE:
+ /* WED txfree queue needs ring to be initialized before setup */
+ q->flags = 0;
+ mt76_dma_queue_reset(dev, q);
+ mt76_dma_rx_fill(dev, q);
+ q->flags = flags;
+
+ ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
+ if (!ret)
+ q->wed_regs = wed->txfree_ring.reg_base;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+static int
+mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ int idx, int n_desc, int bufsize,
+ u32 ring_base)
+{
+ int ret, size;
+
+ spin_lock_init(&q->lock);
+ spin_lock_init(&q->cleanup_lock);
+
+ q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE;
+ q->ndesc = n_desc;
+ q->buf_size = bufsize;
+ q->hw_idx = idx;
+
+ size = q->ndesc * sizeof(struct mt76_desc);
+ q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
+ if (!q->desc)
+ return -ENOMEM;
+
+ size = q->ndesc * sizeof(*q->entry);
+ q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
+ if (!q->entry)
+ return -ENOMEM;
+
+ ret = mt76_dma_wed_setup(dev, q);
+ if (ret)
+ return ret;
+
+ if (q->flags != MT_WED_Q_TXFREE)
+ mt76_dma_queue_reset(dev, q);
+
+ return 0;
+}
+
static void
mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
{
@@ -562,14 +643,29 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
static int
mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
{
- int len, data_len, done = 0;
+ int len, data_len, done = 0, dma_idx;
struct sk_buff *skb;
unsigned char *data;
+ bool check_ddone = false;
bool more;
+ if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
+ q->flags == MT_WED_Q_TXFREE) {
+ dma_idx = Q_READ(dev, q, dma_idx);
+ check_ddone = true;
+ }
+
while (done < budget) {
u32 info;
+ if (check_ddone) {
+ if (q->tail == dma_idx)
+ dma_idx = Q_READ(dev, q, dma_idx);
+
+ if (q->tail == dma_idx)
+ break;
+ }
+
data = mt76_dma_dequeue(dev, q, false, &len, &info, &more);
if (!data)
break;
@@ -710,5 +806,8 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
}
mt76_free_pending_txwi(dev);
+
+ if (mtk_wed_device_active(&dev->mmio.wed))
+ mtk_wed_device_detach(&dev->mmio.wed);
}
EXPORT_SYMBOL_GPL(mt76_dma_cleanup);
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 5b53d008eb66..18b5de55334c 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -248,6 +248,8 @@ static void mt76_init_stream_cap(struct mt76_phy *phy,
vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
else
vht_cap->cap &= ~IEEE80211_VHT_CAP_TXSTBC;
+ vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN |
+ IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN;
for (i = 0; i < 8; i++) {
if (i < nstream)
@@ -323,8 +325,6 @@ mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband,
vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC |
IEEE80211_VHT_CAP_RXSTBC_1 |
IEEE80211_VHT_CAP_SHORT_GI_80 |
- IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
- IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN |
(3 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
return 0;
@@ -545,6 +545,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
dev->hw = hw;
dev->dev = pdev;
dev->drv = drv_ops;
+ dev->dma_dev = pdev;
phy = &dev->phy;
phy->dev = dev;
@@ -579,6 +580,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
INIT_LIST_HEAD(&dev->wcid_list);
INIT_LIST_HEAD(&dev->txwi_cache);
+ dev->token_size = dev->drv->token_size;
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
skb_queue_head_init(&dev->rx_skb[i]);
@@ -1303,7 +1305,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
continue;
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
- mtxq->wcid = wcid;
+ mtxq->wcid = wcid->idx;
}
ewma_signal_init(&wcid->rssi);
@@ -1381,7 +1383,9 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
mutex_lock(&dev->mutex);
+ spin_lock_bh(&dev->status_lock);
rcu_assign_pointer(dev->wcid[wcid->idx], NULL);
+ spin_unlock_bh(&dev->status_lock);
mutex_unlock(&dev->mutex);
}
EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove);
@@ -1578,7 +1582,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna);
struct mt76_queue *
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
- int ring_base)
+ int ring_base, u32 flags)
{
struct mt76_queue *hwq;
int err;
@@ -1587,6 +1591,8 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
if (!hwq)
return ERR_PTR(-ENOMEM);
+ hwq->flags = flags;
+
err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base);
if (err < 0)
return ERR_PTR(err);
diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c
index 3f94c37251df..914ee278e6e2 100644
--- a/drivers/net/wireless/mediatek/mt76/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mcu.c
@@ -6,14 +6,14 @@
#include "mt76.h"
struct sk_buff *
-mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
- int data_len)
+__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
+ int data_len, gfp_t gfp)
{
const struct mt76_mcu_ops *ops = dev->mcu_ops;
int length = ops->headroom + data_len + ops->tailroom;
struct sk_buff *skb;
- skb = alloc_skb(length, GFP_KERNEL);
+ skb = alloc_skb(length, gfp);
if (!skb)
return NULL;
@@ -25,7 +25,7 @@ mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
return skb;
}
-EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc);
+EXPORT_SYMBOL_GPL(__mt76_mcu_msg_alloc);
struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
unsigned long expires)
diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c
index 26353b6bce97..86e3d2ac4d0d 100644
--- a/drivers/net/wireless/mediatek/mt76/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mmio.c
@@ -73,8 +73,13 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
spin_lock_irqsave(&dev->mmio.irq_lock, flags);
dev->mmio.irqmask &= ~clear;
dev->mmio.irqmask |= set;
- if (addr)
- mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
+ if (addr) {
+ if (mtk_wed_device_active(&dev->mmio.wed))
+ mtk_wed_device_irq_set_mask(&dev->mmio.wed,
+ dev->mmio.irqmask);
+ else
+ mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
+ }
spin_unlock_irqrestore(&dev->mmio.irq_lock, flags);
}
EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 882fb5d2517f..4e8997c45c1b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -13,6 +13,7 @@
#include <linux/leds.h>
#include <linux/usb.h>
#include <linux/average.h>
+#include <linux/soc/mediatek/mtk_wed.h>
#include <net/mac80211.h>
#include "util.h"
#include "testmode.h"
@@ -26,6 +27,16 @@
#define MT76_TOKEN_FREE_THR 64
+#define MT_QFLAG_WED_RING GENMASK(1, 0)
+#define MT_QFLAG_WED_TYPE GENMASK(3, 2)
+#define MT_QFLAG_WED BIT(4)
+
+#define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \
+ FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
+ FIELD_PREP(MT_QFLAG_WED_RING, _n))
+#define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n)
+#define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0)
+
struct mt76_dev;
struct mt76_phy;
struct mt76_wcid;
@@ -42,6 +53,11 @@ enum mt76_bus_type {
MT76_BUS_SDIO,
};
+enum mt76_wed_type {
+ MT76_WED_Q_TX,
+ MT76_WED_Q_TXFREE,
+};
+
struct mt76_bus_ops {
u32 (*rr)(struct mt76_dev *dev, u32 offset);
void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
@@ -170,6 +186,9 @@ struct mt76_queue {
u8 buf_offset;
u8 hw_idx;
u8 qid;
+ u8 flags;
+
+ u32 wed_regs;
dma_addr_t desc_dma;
struct sk_buff *rx_head;
@@ -275,7 +294,7 @@ struct mt76_wcid {
};
struct mt76_txq {
- struct mt76_wcid *wcid;
+ u16 wcid;
u16 agg_ssn;
bool send_bar;
@@ -537,6 +556,8 @@ struct mt76_mmio {
void __iomem *regs;
spinlock_t irq_lock;
u32 irqmask;
+
+ struct mtk_wed_device wed;
};
struct mt76_rx_status {
@@ -698,6 +719,7 @@ struct mt76_dev {
const struct mt76_driver_ops *drv;
const struct mt76_mcu_ops *mcu_ops;
struct device *dev;
+ struct device *dma_dev;
struct mt76_mcu mcu;
@@ -718,7 +740,9 @@ struct mt76_dev {
spinlock_t token_lock;
struct idr token;
- int token_count;
+ u16 wed_token_count;
+ u16 token_count;
+ u16 token_size;
wait_queue_head_t tx_wait;
/* spinclock used to protect wcid pktid linked list */
@@ -727,7 +751,7 @@ struct mt76_dev {
u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
- u32 vif_mask;
+ u64 vif_mask;
struct mt76_wcid global_wcid;
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
@@ -942,14 +966,14 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
struct mt76_queue *
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
- int ring_base);
+ int ring_base, u32 flags);
u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx);
static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx,
- int n_desc, int ring_base)
+ int n_desc, int ring_base, u32 flags)
{
struct mt76_queue *q;
- q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base);
+ q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base, flags);
if (IS_ERR(q))
return PTR_ERR(q);
@@ -964,7 +988,7 @@ static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx,
{
struct mt76_queue *q;
- q = mt76_init_queue(dev, qid, idx, n_desc, ring_base);
+ q = mt76_init_queue(dev, qid, idx, n_desc, ring_base, 0);
if (IS_ERR(q))
return PTR_ERR(q);
@@ -1321,8 +1345,15 @@ int mt76s_rd_rp(struct mt76_dev *dev, u32 base,
struct mt76_reg_pair *data, int len);
struct sk_buff *
+__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
+ int data_len, gfp_t gfp);
+static inline struct sk_buff *
mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
- int data_len);
+ int data_len)
+{
+ return __mt76_mcu_msg_alloc(dev, data, data_len, GFP_KERNEL);
+}
+
void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb);
struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
unsigned long expires);
@@ -1380,8 +1411,7 @@ mt76_token_get(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
int token;
spin_lock_bh(&dev->token_lock);
- token = idr_alloc(&dev->token, *ptxwi, 0, dev->drv->token_size,
- GFP_ATOMIC);
+ token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC);
spin_unlock_bh(&dev->token_lock);
return token;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
index 5d4522f440b7..b5e8308e0cc7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
@@ -82,12 +82,12 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
__skb_queue_head_init(&data.q);
q = dev->mphy.q_tx[MT_TXQ_BEACON];
- spin_lock_bh(&q->lock);
+ spin_lock(&q->lock);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7603_update_beacon_iter, dev);
mt76_queue_kick(dev, q);
- spin_unlock_bh(&q->lock);
+ spin_unlock(&q->lock);
/* Flush all previous CAB queue packets */
mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
@@ -117,7 +117,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
mt76_skb_set_moredata(data.tail[i], false);
}
- spin_lock_bh(&q->lock);
+ spin_lock(&q->lock);
while ((skb = __skb_dequeue(&data.q)) != NULL) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
@@ -126,7 +126,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
mt76_tx_queue_skb(dev, q, skb, &mvif->sta.wcid, NULL);
}
mt76_queue_kick(dev, q);
- spin_unlock_bh(&q->lock);
+ spin_unlock(&q->lock);
for (i = 0; i < ARRAY_SIZE(data.count); i++)
mt76_wr(dev, MT_WF_ARB_CAB_COUNT_B0_REG(i),
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
index 37b092e3ea51..f9e5857850e7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
@@ -173,13 +173,13 @@ int mt7603_dma_init(struct mt7603_dev *dev)
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i],
- MT7603_TX_RING_SIZE, MT_TX_RING_BASE);
+ MT7603_TX_RING_SIZE, MT_TX_RING_BASE, 0);
if (ret)
return ret;
}
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT,
- MT7603_PSD_RING_SIZE, MT_TX_RING_BASE);
+ MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, 0);
if (ret)
return ret;
@@ -189,12 +189,12 @@ int mt7603_dma_init(struct mt7603_dev *dev)
return ret;
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN,
- MT_MCU_RING_SIZE, MT_TX_RING_BASE);
+ MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0);
if (ret)
return ret;
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC,
- MT_MCU_RING_SIZE, MT_TX_RING_BASE);
+ MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0);
if (ret)
return ret;
@@ -223,8 +223,8 @@ int mt7603_dma_init(struct mt7603_dev *dev)
if (ret)
return ret;
- netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
- mt7603_poll_tx, NAPI_POLL_WEIGHT);
+ netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
+ mt7603_poll_tx);
napi_enable(&dev->mt76.tx_napi);
return 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index 83c5eec5b163..91425b454cae 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -44,7 +44,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mutex_lock(&dev->mt76.mutex);
- mvif->idx = ffs(~dev->mt76.vif_mask) - 1;
+ mvif->idx = __ffs64(~dev->mt76.vif_mask);
if (mvif->idx >= MT7603_MAX_INTERFACES) {
ret = -ENOSPC;
goto out;
@@ -65,7 +65,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
}
idx = MT7603_WTBL_RESERVED - 1 - mvif->idx;
- dev->mt76.vif_mask |= BIT(mvif->idx);
+ dev->mt76.vif_mask |= BIT_ULL(mvif->idx);
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.hw_key_idx = -1;
@@ -75,7 +75,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
- mtxq->wcid = &mvif->sta.wcid;
+ mtxq->wcid = idx;
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
out:
@@ -106,7 +106,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
spin_unlock_bh(&dev->sta_poll_lock);
mutex_lock(&dev->mt76.mutex);
- dev->mt76.vif_mask &= ~BIT(mvif->idx);
+ dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
mutex_unlock(&dev->mt76.mutex);
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
index 00aefea1bf61..ce19f57de475 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
@@ -26,14 +26,14 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i],
MT7615_TX_RING_SIZE / 2,
- MT_TX_RING_BASE);
+ MT_TX_RING_BASE, 0);
if (ret)
return ret;
}
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT7622_TXQ_MGMT,
MT7615_TX_MGMT_RING_SIZE,
- MT_TX_RING_BASE);
+ MT_TX_RING_BASE, 0);
if (ret)
return ret;
@@ -55,7 +55,7 @@ mt7615_init_tx_queues(struct mt7615_dev *dev)
return mt7622_init_tx_queues_multi(dev);
ret = mt76_init_tx_queue(&dev->mphy, 0, 0, MT7615_TX_RING_SIZE,
- MT_TX_RING_BASE);
+ MT_TX_RING_BASE, 0);
if (ret)
return ret;
@@ -284,8 +284,8 @@ int mt7615_dma_init(struct mt7615_dev *dev)
if (ret < 0)
return ret;
- netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
- mt7615_poll_tx, NAPI_POLL_WEIGHT);
+ netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
+ mt7615_poll_tx);
napi_enable(&dev->mt76.tx_napi);
mt76_poll(dev, MT_WPDMA_GLO_CFG,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index d79cbdbd5a05..a9c9b97d173e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -194,7 +194,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
is_zero_ether_addr(vif->addr))
phy->monitor_vif = vif;
- mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1;
+ mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);
if (mvif->mt76.idx >= MT7615_MAX_INTERFACES) {
ret = -ENOSPC;
goto out;
@@ -212,7 +212,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
if (ext_phy)
mvif->mt76.wmm_idx += 2;
- dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
+ dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
@@ -234,7 +234,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
if (vif->txq) {
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
- mtxq->wcid = &mvif->sta.wcid;
+ mtxq->wcid = idx;
}
ret = mt7615_mcu_add_dev_info(phy, vif, true);
@@ -268,7 +268,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
- dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx);
+ dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
dev->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
index ce45c3bfc443..a208035e197a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
@@ -145,7 +145,7 @@ static void mt7615_irq_tasklet(struct tasklet_struct *t)
return;
dev->reset_state = mcu_int;
- ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
+ queue_work(dev->mt76.wq, &dev->reset_work);
wake_up(&dev->reset_wait);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 51a9b5d60c7a..faa279bbbcb2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -2185,11 +2185,8 @@ int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev,
return -ENOMEM;
skb_put_data(skb, &req_hdr, sizeof(req_hdr));
- for (i = 0; i < len; i++) {
- u8 *addr = (u8 *)skb_put(skb, sizeof(__be32));
-
- memcpy(addr, &info->arp_addr_list[i], sizeof(__be32));
- }
+ for (i = 0; i < len; i++)
+ skb_put_data(skb, &info->arp_addr_list[i], sizeof(__be32));
return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(OFFLOAD), true);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index c3c93338d56a..561fb0368708 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -974,7 +974,6 @@ enum {
MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d,
MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
MCU_EXT_CMD_SET_SER_TRIGGER = 0x81,
- MCU_EXT_CMD_SCS_CTRL = 0x82,
MCU_EXT_CMD_TWT_AGRT_UPDATE = 0x94,
MCU_EXT_CMD_FW_DBG_CTRL = 0x95,
MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index 8bcd8afa0d3a..96ec96df6a3c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -191,13 +191,13 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
ret = mt76_init_tx_queue(&dev->mphy, i, mt76_ac_to_hwq(i),
MT76x02_TX_RING_SIZE,
- MT_TX_RING_BASE);
+ MT_TX_RING_BASE, 0);
if (ret)
return ret;
}
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT,
- MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE);
+ MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE, 0);
if (ret)
return ret;
@@ -230,8 +230,8 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
if (ret)
return ret;
- netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
- mt76x02_poll_tx, NAPI_POLL_WEIGHT);
+ netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
+ mt76x02_poll_tx);
napi_enable(&dev->mt76.tx_napi);
return 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index dd30f537676d..5bd0a0bae688 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -292,7 +292,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
mt76_packet_id_init(&mvif->group_wcid);
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
- mtxq->wcid = &mvif->group_wcid;
+ rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid);
+ mtxq->wcid = MT_VIF_WCID(idx);
}
int
@@ -327,11 +328,11 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
idx += 8;
/* vif is already set or idx is 8 for AP/Mesh/... */
- if (dev->mt76.vif_mask & BIT(idx) ||
+ if (dev->mt76.vif_mask & BIT_ULL(idx) ||
(vif->type != NL80211_IFTYPE_STATION && idx > 7))
return -EBUSY;
- dev->mt76.vif_mask |= BIT(idx);
+ dev->mt76.vif_mask |= BIT_ULL(idx);
mt76x02_vif_init(dev, vif, idx);
return 0;
@@ -344,7 +345,8 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
struct mt76x02_dev *dev = hw->priv;
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
- dev->mt76.vif_mask &= ~BIT(mvif->idx);
+ dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
+ rcu_assign_pointer(dev->mt76.wcid[mvif->group_wcid.idx], NULL);
mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid);
}
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
index e9cab1165f38..cab6e02e1f8c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
@@ -44,35 +44,113 @@ mt7915_implicit_txbf_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get,
mt7915_implicit_txbf_set, "%lld\n");
-/* test knob of system layer 1/2 error recovery */
-static int mt7915_ser_trigger_set(void *data, u64 val)
+/* test knob of system error recovery */
+static ssize_t
+mt7915_fw_ser_set(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- enum {
- SER_SET_RECOVER_L1 = 1,
- SER_SET_RECOVER_L2,
- SER_ENABLE = 2,
- SER_RECOVER
- };
- struct mt7915_dev *dev = data;
+ struct mt7915_phy *phy = file->private_data;
+ struct mt7915_dev *dev = phy->dev;
+ bool ext_phy = phy != &dev->phy;
+ char buf[16];
int ret = 0;
+ u16 val;
+
+ if (count >= sizeof(buf))
+ return -EINVAL;
+
+ if (copy_from_user(buf, user_buf, count))
+ return -EFAULT;
+
+ if (count && buf[count - 1] == '\n')
+ buf[count - 1] = '\0';
+ else
+ buf[count] = '\0';
+
+ if (kstrtou16(buf, 0, &val))
+ return -EINVAL;
switch (val) {
+ case SER_QUERY:
+ /* grab firmware SER stats */
+ ret = mt7915_mcu_set_ser(dev, 0, 0, ext_phy);
+ break;
case SER_SET_RECOVER_L1:
case SER_SET_RECOVER_L2:
- ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), 0);
+ case SER_SET_RECOVER_L3_RX_ABORT:
+ case SER_SET_RECOVER_L3_TX_ABORT:
+ case SER_SET_RECOVER_L3_TX_DISABLE:
+ case SER_SET_RECOVER_L3_BF:
+ ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), ext_phy);
if (ret)
return ret;
- return mt7915_mcu_set_ser(dev, SER_RECOVER, val, 0);
+ ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, ext_phy);
+ break;
default:
break;
}
+ return ret ? ret : count;
+}
+
+static ssize_t
+mt7915_fw_ser_get(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct mt7915_phy *phy = file->private_data;
+ struct mt7915_dev *dev = phy->dev;
+ char *buff;
+ int desc = 0;
+ ssize_t ret;
+ static const size_t bufsz = 400;
+
+ buff = kmalloc(bufsz, GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_STATUS = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_SER_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_PLE_ERR = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_PLE_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_PLE_ERR_1 = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_PLE1_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_PLE_ERR_AMSDU = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_PSE_ERR = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_PSE_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_PSE_ERR_1 = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_PSE1_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_LMAC_WISR6_B0 = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_LMAC_WISR6_B1 = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_LMAC_WISR7_B0 = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS));
+ desc += scnprintf(buff + desc, bufsz - desc,
+ "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+ kfree(buff);
return ret;
}
-DEFINE_DEBUGFS_ATTRIBUTE(fops_ser_trigger, NULL,
- mt7915_ser_trigger_set, "%lld\n");
+static const struct file_operations mt7915_fw_ser_ops = {
+ .write = mt7915_fw_ser_set,
+ .read = mt7915_fw_ser_get,
+ .open = simple_open,
+ .llseek = default_llseek,
+};
static int
mt7915_radar_trigger(void *data, u64 val)
@@ -95,7 +173,7 @@ mt7915_muru_debug_set(void *data, u64 val)
struct mt7915_dev *dev = data;
dev->muru_debug = val;
- mt7915_mcu_muru_debug_set(dev, data);
+ mt7915_mcu_muru_debug_set(dev, dev->muru_debug);
return 0;
}
@@ -369,20 +447,20 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
bool tx, rx, en;
int ret;
- dev->fw_debug_wm = val ? MCU_FW_LOG_TO_HOST : 0;
+ dev->fw.debug_wm = val ? MCU_FW_LOG_TO_HOST : 0;
- if (dev->fw_debug_bin)
+ if (dev->fw.debug_bin)
val = 16;
else
- val = dev->fw_debug_wm;
+ val = dev->fw.debug_wm;
- tx = dev->fw_debug_wm || (dev->fw_debug_bin & BIT(1));
- rx = dev->fw_debug_wm || (dev->fw_debug_bin & BIT(2));
- en = dev->fw_debug_wm || (dev->fw_debug_bin & BIT(0));
+ tx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(1));
+ rx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(2));
+ en = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(0));
ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, val);
if (ret)
- return ret;
+ goto out;
for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RX; debug++) {
if (debug == DEBUG_RPT_RX)
@@ -392,16 +470,20 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
ret = mt7915_mcu_fw_dbg_ctrl(dev, debug, val);
if (ret)
- return ret;
+ goto out;
}
/* WM CPU info record control */
mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0));
- mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw_debug_wm);
+ mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw.debug_wm);
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5));
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5));
- return 0;
+out:
+ if (ret)
+ dev->fw.debug_wm = 0;
+
+ return ret;
}
static int
@@ -409,7 +491,7 @@ mt7915_fw_debug_wm_get(void *data, u64 *val)
{
struct mt7915_dev *dev = data;
- *val = dev->fw_debug_wm;
+ *val = dev->fw.debug_wm;
return 0;
}
@@ -423,14 +505,19 @@ mt7915_fw_debug_wa_set(void *data, u64 val)
struct mt7915_dev *dev = data;
int ret;
- dev->fw_debug_wa = val ? MCU_FW_LOG_TO_HOST : 0;
+ dev->fw.debug_wa = val ? MCU_FW_LOG_TO_HOST : 0;
- ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw_debug_wa);
+ ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw.debug_wa);
if (ret)
- return ret;
+ goto out;
- return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), MCU_WA_PARAM_PDMA_RX,
- !!dev->fw_debug_wa, 0);
+ ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
+ MCU_WA_PARAM_PDMA_RX, !!dev->fw.debug_wa, 0);
+out:
+ if (ret)
+ dev->fw.debug_wa = 0;
+
+ return ret;
}
static int
@@ -438,7 +525,7 @@ mt7915_fw_debug_wa_get(void *data, u64 *val)
{
struct mt7915_dev *dev = data;
- *val = dev->fw_debug_wa;
+ *val = dev->fw.debug_wa;
return 0;
}
@@ -485,11 +572,11 @@ mt7915_fw_debug_bin_set(void *data, u64 val)
if (!dev->relay_fwlog)
return -ENOMEM;
- dev->fw_debug_bin = val;
+ dev->fw.debug_bin = val;
relay_reset(dev->relay_fwlog);
- return mt7915_fw_debug_wm_set(dev, dev->fw_debug_wm);
+ return mt7915_fw_debug_wm_set(dev, dev->fw.debug_wm);
}
static int
@@ -497,7 +584,7 @@ mt7915_fw_debug_bin_get(void *data, u64 *val)
{
struct mt7915_dev *dev = data;
- *val = dev->fw_debug_bin;
+ *val = dev->fw.debug_bin;
return 0;
}
@@ -510,7 +597,13 @@ mt7915_fw_util_wm_show(struct seq_file *file, void *data)
{
struct mt7915_dev *dev = file->private;
- if (dev->fw_debug_wm) {
+ seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WM_MCU_PC));
+ seq_printf(file, "Exception state: 0x%x\n",
+ is_mt7915(&dev->mt76) ?
+ (u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(15, 8)) :
+ (u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(7, 0)));
+
+ if (dev->fw.debug_wm) {
seq_printf(file, "Busy: %u%% Peak busy: %u%%\n",
mt76_rr(dev, MT_CPU_UTIL_BUSY_PCT),
mt76_rr(dev, MT_CPU_UTIL_PEAK_BUSY_PCT));
@@ -529,7 +622,9 @@ mt7915_fw_util_wa_show(struct seq_file *file, void *data)
{
struct mt7915_dev *dev = file->private;
- if (dev->fw_debug_wa)
+ seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WA_MCU_PC));
+
+ if (dev->fw.debug_wa)
return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(QUERY),
MCU_WA_PARAM_CPU_UTIL, 0, 0);
@@ -867,6 +962,36 @@ mt7915_twt_stats(struct seq_file *s, void *data)
return 0;
}
+/* The index of RF registers use the generic regidx, combined with two parts:
+ * WF selection [31:28] and offset [27:0].
+ */
+static int
+mt7915_rf_regval_get(void *data, u64 *val)
+{
+ struct mt7915_dev *dev = data;
+ u32 regval;
+ int ret;
+
+ ret = mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, &regval, false);
+ if (ret)
+ return ret;
+
+ *val = le32_to_cpu(regval);
+
+ return 0;
+}
+
+static int
+mt7915_rf_regval_set(void *data, u64 val)
+{
+ struct mt7915_dev *dev = data;
+
+ return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, (u32 *)&val, true);
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7915_rf_regval_get,
+ mt7915_rf_regval_set, "0x%08llx\n");
+
int mt7915_init_debugfs(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
@@ -884,6 +1009,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
debugfs_create_file("xmit-queues", 0400, dir, phy,
&mt7915_xmit_queues_fops);
debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops);
+ debugfs_create_file("fw_ser", 0600, dir, phy, &mt7915_fw_ser_ops);
debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin);
@@ -897,7 +1023,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
&mt7915_rate_txpower_fops);
debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
mt7915_twt_stats);
- debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger);
+ debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
+
if (!dev->dbdc_support || phy->band_idx) {
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
&dev->hw_pattern);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
index 49b4d8ade16b..f3d608d2d3b2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
@@ -5,11 +5,19 @@
#include "../dma.h"
#include "mac.h"
-int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base)
+static int
+mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base)
{
+ struct mt7915_dev *dev = phy->dev;
int i, err;
- err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base);
+ if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
+ ring_base = MT_WED_TX_RING_BASE;
+ idx -= MT_TXQ_ID(0);
+ }
+
+ err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base,
+ MT_WED_Q_TX(idx));
if (err < 0)
return err;
@@ -318,14 +326,23 @@ static int mt7915_dma_enable(struct mt7915_dev *dev)
if (dev->dbdc_support || dev->phy.band_idx)
irq_mask |= MT_INT_BAND1_RX_DONE;
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+ u32 wed_irq_mask = irq_mask;
+
+ wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
+ mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask);
+ mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
+ }
+
mt7915_irq_enable(dev, irq_mask);
return 0;
}
-int mt7915_dma_init(struct mt7915_dev *dev)
+int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
{
struct mt76_dev *mdev = &dev->mt76;
+ u32 wa_rx_base, wa_rx_idx;
u32 hif1_ofs = 0;
int ret;
@@ -338,6 +355,17 @@ int mt7915_dma_init(struct mt7915_dev *dev)
mt7915_dma_disable(dev, true);
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+ mt76_set(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
+
+ mt76_wr(dev, MT_WFDMA_WED_RING_CONTROL,
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX0, 18) |
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX1, 19) |
+ FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_RX1, 1));
+ } else {
+ mt76_clear(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
+ }
+
/* init tx queue */
ret = mt7915_init_tx_queues(&dev->phy,
MT_TXQ_ID(dev->phy.band_idx),
@@ -346,6 +374,15 @@ int mt7915_dma_init(struct mt7915_dev *dev)
if (ret)
return ret;
+ if (phy2) {
+ ret = mt7915_init_tx_queues(phy2,
+ MT_TXQ_ID(phy2->band_idx),
+ MT7915_TX_RING_SIZE,
+ MT_TXQ_RING_BASE(1));
+ if (ret)
+ return ret;
+ }
+
/* command to WM */
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM,
MT_MCUQ_ID(MT_MCUQ_WM),
@@ -380,11 +417,17 @@ int mt7915_dma_init(struct mt7915_dev *dev)
return ret;
/* event from WA */
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
+ wa_rx_base = MT_WED_RX_RING_BASE;
+ wa_rx_idx = MT7915_RXQ_MCU_WA;
+ dev->mt76.q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE;
+ } else {
+ wa_rx_base = MT_RXQ_RING_BASE(MT_RXQ_MCU_WA);
+ wa_rx_idx = MT_RXQ_ID(MT_RXQ_MCU_WA);
+ }
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
- MT_RXQ_ID(MT_RXQ_MCU_WA),
- MT7915_RX_MCU_RING_SIZE,
- MT_RX_BUF_SIZE,
- MT_RXQ_RING_BASE(MT_RXQ_MCU_WA));
+ wa_rx_idx, MT7915_RX_MCU_RING_SIZE,
+ MT_RX_BUF_SIZE, wa_rx_base);
if (ret)
return ret;
@@ -434,8 +477,8 @@ int mt7915_dma_init(struct mt7915_dev *dev)
if (ret < 0)
return ret;
- netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
- mt7915_poll_tx, NAPI_POLL_WEIGHT);
+ netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
+ mt7915_poll_tx);
napi_enable(&dev->mt76.tx_napi);
mt7915_dma_enable(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
index 5b133bcdab17..4b1a9811646f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
@@ -152,6 +152,8 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
phy->mt76->cap.has_2ghz = true;
return;
}
+ } else if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) {
+ val = phy->band_idx ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
}
switch (val) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 6d29366c5139..01169853355e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -351,6 +351,8 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
if (!mdev->dev->of_node ||
!of_property_read_bool(mdev->dev->of_node,
@@ -450,6 +452,9 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, rx_len);
+ if (!is_mt7915(&dev->mt76))
+ mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);
+
/* enable hardware de-agg */
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
@@ -484,21 +489,18 @@ static int mt7915_txbf_init(struct mt7915_dev *dev)
return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);
}
-static int mt7915_register_ext_phy(struct mt7915_dev *dev)
+static struct mt7915_phy *
+mt7915_alloc_ext_phy(struct mt7915_dev *dev)
{
- struct mt7915_phy *phy = mt7915_ext_phy(dev);
+ struct mt7915_phy *phy;
struct mt76_phy *mphy;
- int ret;
if (!dev->dbdc_support)
- return 0;
-
- if (phy)
- return 0;
+ return NULL;
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops);
if (!mphy)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
phy = mphy->priv;
phy->dev = dev;
@@ -507,6 +509,15 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
/* Bind main phy to band0 and ext_phy to band1 for dbdc case */
phy->band_idx = 1;
+ return phy;
+}
+
+static int
+mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)
+{
+ struct mt76_phy *mphy = phy->mt76;
+ int ret;
+
INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work);
mt7915_eeprom_parse_hw_cap(dev, phy);
@@ -526,29 +537,22 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
/* init wiphy according to mphy and phy */
mt7915_init_wiphy(mphy->hw);
- ret = mt7915_init_tx_queues(phy, MT_TXQ_ID(phy->band_idx),
- MT7915_TX_RING_SIZE,
- MT_TXQ_RING_BASE(1));
- if (ret)
- goto error;
ret = mt76_register_phy(mphy, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret)
- goto error;
+ return ret;
ret = mt7915_thermal_init(phy);
if (ret)
- goto error;
+ goto unreg;
- ret = mt7915_init_debugfs(phy);
- if (ret)
- goto error;
+ mt7915_init_debugfs(phy);
return 0;
-error:
- ieee80211_free_hw(mphy->hw);
+unreg:
+ mt76_unregister_phy(mphy);
return ret;
}
@@ -565,7 +569,7 @@ static void mt7915_init_work(struct work_struct *work)
mt7915_txbf_init(dev);
}
-static void mt7915_wfsys_reset(struct mt7915_dev *dev)
+void mt7915_wfsys_reset(struct mt7915_dev *dev)
{
#define MT_MCU_DUMMY_RANDOM GENMASK(15, 0)
#define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16)
@@ -645,36 +649,25 @@ static bool mt7915_band_config(struct mt7915_dev *dev)
return ret;
}
-static int mt7915_init_hardware(struct mt7915_dev *dev)
+static int
+mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2)
{
int ret, idx;
+ mt76_wr(dev, MT_INT_MASK_CSR, 0);
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
INIT_WORK(&dev->init_work, mt7915_init_work);
- dev->dbdc_support = mt7915_band_config(dev);
-
- /* If MCU was already running, it is likely in a bad state */
- if (mt76_get_field(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE) >
- FW_STATE_FW_DOWNLOAD)
- mt7915_wfsys_reset(dev);
-
- ret = mt7915_dma_init(dev);
+ ret = mt7915_dma_init(dev, phy2);
if (ret)
return ret;
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
ret = mt7915_mcu_init(dev);
- if (ret) {
- /* Reset and try again */
- mt7915_wfsys_reset(dev);
-
- ret = mt7915_mcu_init(dev);
- if (ret)
- return ret;
- }
+ if (ret)
+ return ret;
ret = mt7915_eeprom_init(dev);
if (ret < 0)
@@ -814,7 +807,7 @@ static void
mt7915_gen_ppe_thresh(u8 *he_ppet, int nss)
{
u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
- u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
+ static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) |
FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK,
@@ -1048,9 +1041,22 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
ieee80211_free_hw(mphy->hw);
}
+static void mt7915_stop_hardware(struct mt7915_dev *dev)
+{
+ mt7915_mcu_exit(dev);
+ mt7915_tx_token_put(dev);
+ mt7915_dma_cleanup(dev);
+ tasklet_disable(&dev->irq_tasklet);
+
+ if (is_mt7986(&dev->mt76))
+ mt7986_wmac_disable(dev);
+}
+
+
int mt7915_register_device(struct mt7915_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
+ struct mt7915_phy *phy2;
int ret;
dev->phy.dev = dev;
@@ -1066,9 +1072,15 @@ int mt7915_register_device(struct mt7915_dev *dev)
init_waitqueue_head(&dev->reset_wait);
INIT_WORK(&dev->reset_work, mt7915_mac_reset_work);
- ret = mt7915_init_hardware(dev);
+ dev->dbdc_support = mt7915_band_config(dev);
+
+ phy2 = mt7915_alloc_ext_phy(dev);
+ if (IS_ERR(phy2))
+ return PTR_ERR(phy2);
+
+ ret = mt7915_init_hardware(dev, phy2);
if (ret)
- return ret;
+ goto free_phy2;
mt7915_init_wiphy(hw);
@@ -1085,19 +1097,34 @@ int mt7915_register_device(struct mt7915_dev *dev)
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret)
- return ret;
+ goto stop_hw;
ret = mt7915_thermal_init(&dev->phy);
if (ret)
- return ret;
+ goto unreg_dev;
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
- ret = mt7915_register_ext_phy(dev);
- if (ret)
- return ret;
+ if (phy2) {
+ ret = mt7915_register_ext_phy(dev, phy2);
+ if (ret)
+ goto unreg_thermal;
+ }
+
+ mt7915_init_debugfs(&dev->phy);
+
+ return 0;
- return mt7915_init_debugfs(&dev->phy);
+unreg_thermal:
+ mt7915_unregister_thermal(&dev->phy);
+unreg_dev:
+ mt76_unregister_device(&dev->mt76);
+stop_hw:
+ mt7915_stop_hardware(dev);
+free_phy2:
+ if (phy2)
+ ieee80211_free_hw(phy2->mt76->hw);
+ return ret;
}
void mt7915_unregister_device(struct mt7915_dev *dev)
@@ -1105,13 +1132,7 @@ void mt7915_unregister_device(struct mt7915_dev *dev)
mt7915_unregister_ext_phy(dev);
mt7915_unregister_thermal(&dev->phy);
mt76_unregister_device(&dev->mt76);
- mt7915_mcu_exit(dev);
- mt7915_tx_token_put(dev);
- mt7915_dma_cleanup(dev);
- tasklet_disable(&dev->irq_tasklet);
-
- if (is_mt7986(&dev->mt76))
- mt7986_wmac_disable(dev);
+ mt7915_stop_hardware(dev);
mt76_free_device(&dev->mt76);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index bab70cf981bb..086244d9be76 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -309,7 +309,7 @@ mt7915_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
}
static void
-mt7915_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode)
+mt7915_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
static const struct ieee80211_radiotap_he known = {
@@ -474,10 +474,10 @@ static int
mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
struct mt76_rx_status *status,
struct ieee80211_supported_band *sband,
- __le32 *rxv)
+ __le32 *rxv, u8 *mode)
{
u32 v0, v2;
- u8 stbc, gi, bw, dcm, mode, nss;
+ u8 stbc, gi, bw, dcm, nss;
int i, idx;
bool cck = false;
@@ -490,18 +490,18 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
if (!is_mt7915(&dev->mt76)) {
stbc = FIELD_GET(MT_PRXV_HT_STBC, v0);
gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v0);
- mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
+ *mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
dcm = FIELD_GET(MT_PRXV_DCM, v0);
bw = FIELD_GET(MT_PRXV_FRAME_MODE, v0);
} else {
stbc = FIELD_GET(MT_CRXV_HT_STBC, v2);
gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2);
- mode = FIELD_GET(MT_CRXV_TX_MODE, v2);
+ *mode = FIELD_GET(MT_CRXV_TX_MODE, v2);
dcm = !!(idx & GENMASK(3, 0) & MT_PRXV_TX_DCM);
bw = FIELD_GET(MT_CRXV_FRAME_MODE, v2);
}
- switch (mode) {
+ switch (*mode) {
case MT_PHY_TYPE_CCK:
cck = true;
fallthrough;
@@ -521,7 +521,7 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
status->encoding = RX_ENC_VHT;
if (gi)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
- if (i > 9)
+ if (i > 11)
return -EINVAL;
break;
case MT_PHY_TYPE_HE_MU:
@@ -546,7 +546,7 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
case IEEE80211_STA_RX_BW_20:
break;
case IEEE80211_STA_RX_BW_40:
- if (mode & MT_PHY_TYPE_HE_EXT_SU &&
+ if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
(idx & MT_PRXV_TX_ER_SU_106T)) {
status->bw = RATE_INFO_BW_HE_RU;
status->he_ru =
@@ -566,7 +566,7 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
}
status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
- if (mode < MT_PHY_TYPE_HE_SU && gi)
+ if (*mode < MT_PHY_TYPE_HE_SU && gi)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
return 0;
@@ -581,7 +581,6 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
struct ieee80211_supported_band *sband;
__le32 *rxd = (__le32 *)skb->data;
__le32 *rxv = NULL;
- u32 mode = 0;
u32 rxd0 = le32_to_cpu(rxd[0]);
u32 rxd1 = le32_to_cpu(rxd[1]);
u32 rxd2 = le32_to_cpu(rxd[2]);
@@ -590,10 +589,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
bool unicast, insert_ccmp_hdr = false;
u8 remove_pad, amsdu_info;
+ u8 mode = 0, qos_ctl = 0;
bool hdr_trans;
u16 hdr_gap;
u16 seq_ctrl = 0;
- u8 qos_ctl = 0;
__le16 fc = 0;
int idx;
@@ -766,7 +765,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
}
if (!is_mt7915(&dev->mt76) || (rxd1 & MT_RXD1_NORMAL_GROUP_5)) {
- ret = mt7915_mac_fill_rx_rate(dev, status, sband, rxv);
+ ret = mt7915_mac_fill_rx_rate(dev, status, sband, rxv,
+ &mode);
if (ret < 0)
return ret;
}
@@ -837,10 +837,6 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
if (!status->wcid || !ieee80211_is_data_qos(fc))
return 0;
- /* drop no data frame */
- if (fc & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))
- return -EINVAL;
-
status->aggr = unicast &&
!ieee80211_is_qos_nullfunc(fc);
status->qos_ctl = qos_ctl;
@@ -864,8 +860,11 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
int i;
band_idx = le32_get_bits(rxv_hdr[1], MT_RXV_HDR_BAND_IDX);
- if (band_idx && !phy->band_idx)
+ if (band_idx && !phy->band_idx) {
phy = mt7915_ext_phy(dev);
+ if (!phy)
+ goto out;
+ }
rcpi = le32_to_cpu(rxv[6]);
ib_rssi = le32_to_cpu(rxv[7]);
@@ -890,8 +889,8 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
phy->test.last_freq_offset = foe;
phy->test.last_snr = snr;
+out:
#endif
-
dev_kfree_skb(skb);
}
@@ -1017,6 +1016,7 @@ mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi,
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
u8 fc_type, fc_stype;
+ u16 ethertype;
bool wmm = false;
u32 val;
@@ -1030,7 +1030,8 @@ mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi,
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
FIELD_PREP(MT_TXD1_TID, tid);
- if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN)
+ ethertype = get_unaligned_be16(&skb->data[12]);
+ if (ethertype >= ETH_P_802_3_MIN)
val |= MT_TXD1_ETH_802_3;
txwi[1] |= cpu_to_le32(val);
@@ -1176,7 +1177,7 @@ out:
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
- struct ieee80211_key_conf *key, bool beacon)
+ struct ieee80211_key_conf *key, u32 changed)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
@@ -1187,6 +1188,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
bool mcast = false;
u16 tx_count = 15;
u32 val;
+ bool beacon = !!(changed & (BSS_CHANGED_BEACON |
+ BSS_CHANGED_BEACON_ENABLED));
+ bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
+ BSS_CHANGED_FILS_DISCOVERY));
if (vif) {
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
@@ -1199,7 +1204,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
if (ext_phy && dev->mt76.phy2)
mphy = dev->mt76.phy2;
- if (beacon) {
+ if (inband_disc) {
+ p_fmt = MT_TX_TYPE_FW;
+ q_idx = MT_LMAC_ALTX0;
+ } else if (beacon) {
p_fmt = MT_TX_TYPE_FW;
q_idx = MT_LMAC_BCN0;
} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
@@ -1307,8 +1315,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return id;
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
- mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
- false);
+ mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, 0);
txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
for (i = 0; i < nbuf; i++) {
@@ -1347,6 +1354,29 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return 0;
}
+u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
+{
+ struct mt7915_txp *txp = ptr + MT_TXD_SIZE;
+ __le32 *txwi = ptr;
+ u32 val;
+
+ memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp));
+
+ val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) |
+ FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT);
+ txwi[0] = cpu_to_le32(val);
+
+ val = MT_TXD1_LONG_FORMAT |
+ FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3);
+ txwi[1] = cpu_to_le32(val);
+
+ txp->token = cpu_to_le16(token_id);
+ txp->nbuf = 1;
+ txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp));
+
+ return MT_TXD_SIZE + sizeof(*txp);
+}
+
static void
mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
{
@@ -1380,7 +1410,7 @@ mt7915_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
txp = mt7915_txwi_to_txp(dev, t);
for (i = 0; i < txp->nbuf; i++)
- dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
+ dma_unmap_single(dev->dma_dev, le32_to_cpu(txp->buf[i]),
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
}
@@ -1389,6 +1419,7 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta, struct list_head *free_list)
{
struct mt76_dev *mdev = &dev->mt76;
+ struct mt7915_sta *msta;
struct mt76_wcid *wcid;
__le32 *txwi;
u16 wcid_idx;
@@ -1401,13 +1432,24 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
if (sta) {
wcid = (struct mt76_wcid *)sta->drv_priv;
wcid_idx = wcid->idx;
-
- if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
- mt7915_tx_check_aggr(sta, txwi);
} else {
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
+ wcid = rcu_dereference(dev->mt76.wcid[wcid_idx]);
+
+ if (wcid && wcid->sta) {
+ msta = container_of(wcid, struct mt7915_sta, wcid);
+ sta = container_of((void *)msta, struct ieee80211_sta,
+ drv_priv);
+ spin_lock_bh(&dev->sta_poll_lock);
+ if (list_empty(&msta->poll_list))
+ list_add_tail(&msta->poll_list, &dev->sta_poll_list);
+ spin_unlock_bh(&dev->sta_poll_lock);
+ }
}
+ if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
+ mt7915_tx_check_aggr(sta, txwi);
+
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
out:
@@ -1416,28 +1458,54 @@ out:
}
static void
+mt7915_mac_tx_free_prepare(struct mt7915_dev *dev)
+{
+ struct mt76_dev *mdev = &dev->mt76;
+ struct mt76_phy *mphy_ext = mdev->phy2;
+
+ /* clean DMA queues and unmap buffers first */
+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
+ if (mphy_ext) {
+ mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false);
+ mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false);
+ }
+}
+
+static void
+mt7915_mac_tx_free_done(struct mt7915_dev *dev,
+ struct list_head *free_list, bool wake)
+{
+ struct sk_buff *skb, *tmp;
+
+ mt7915_mac_sta_poll(dev);
+
+ if (wake)
+ mt76_set_tx_blocked(&dev->mt76, false);
+
+ mt76_worker_schedule(&dev->mt76.tx_worker);
+
+ list_for_each_entry_safe(skb, tmp, free_list, list) {
+ skb_list_del_init(skb);
+ napi_consume_skb(skb, 1);
+ }
+}
+
+static void
mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
{
struct mt7915_tx_free *free = (struct mt7915_tx_free *)data;
struct mt76_dev *mdev = &dev->mt76;
- struct mt76_phy *mphy_ext = mdev->phy2;
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
LIST_HEAD(free_list);
- struct sk_buff *skb, *tmp;
void *end = data + len;
bool v3, wake = false;
u16 total, count = 0;
u32 txd = le32_to_cpu(free->txd);
__le32 *cur_info;
- /* clean DMA queues and unmap buffers first */
- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
- if (mphy_ext) {
- mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false);
- mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false);
- }
+ mt7915_mac_tx_free_prepare(dev);
total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4);
@@ -1491,17 +1559,38 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
}
}
- mt7915_mac_sta_poll(dev);
+ mt7915_mac_tx_free_done(dev, &free_list, wake);
+}
- if (wake)
- mt76_set_tx_blocked(&dev->mt76, false);
+static void
+mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len)
+{
+ struct mt7915_tx_free *free = (struct mt7915_tx_free *)data;
+ struct mt76_dev *mdev = &dev->mt76;
+ __le16 *info = (__le16 *)free->info;
+ void *end = data + len;
+ LIST_HEAD(free_list);
+ bool wake = false;
+ u8 i, count;
- mt76_worker_schedule(&dev->mt76.tx_worker);
+ mt7915_mac_tx_free_prepare(dev);
- list_for_each_entry_safe(skb, tmp, &free_list, list) {
- skb_list_del_init(skb);
- napi_consume_skb(skb, 1);
+ count = FIELD_GET(MT_TX_FREE_MSDU_CNT_V0, le16_to_cpu(free->ctrl));
+ if (WARN_ON_ONCE((void *)&info[count] > end))
+ return;
+
+ for (i = 0; i < count; i++) {
+ struct mt76_txwi_cache *txwi;
+ u16 msdu = le16_to_cpu(info[i]);
+
+ txwi = mt76_token_release(mdev, msdu, &wake);
+ if (!txwi)
+ continue;
+
+ mt7915_txwi_free(dev, txwi, NULL, &free_list);
}
+
+ mt7915_mac_tx_free_done(dev, &free_list, wake);
}
static bool
@@ -1681,6 +1770,9 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
case PKT_TYPE_TXRX_NOTIFY:
mt7915_mac_tx_free(dev, data, len);
return false;
+ case PKT_TYPE_TXRX_NOTIFY_V0:
+ mt7915_mac_tx_free_v0(dev, data, len);
+ return false;
case PKT_TYPE_TXS:
for (rxd += 2; rxd + 8 <= end; rxd += 8)
mt7915_mac_add_txs(dev, rxd);
@@ -1708,6 +1800,10 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
mt7915_mac_tx_free(dev, skb->data, skb->len);
napi_consume_skb(skb, 1);
break;
+ case PKT_TYPE_TXRX_NOTIFY_V0:
+ mt7915_mac_tx_free_v0(dev, skb->data, skb->len);
+ napi_consume_skb(skb, 1);
+ break;
case PKT_TYPE_RX_EVENT:
mt7915_mcu_rx_event(dev, skb);
break;
@@ -1918,7 +2014,8 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
- mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon);
+ mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon,
+ BSS_CHANGED_BEACON_ENABLED);
break;
default:
break;
@@ -2304,6 +2401,32 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
}
}
+static void mt7915_mac_severe_check(struct mt7915_phy *phy)
+{
+ struct mt7915_dev *dev = phy->dev;
+ bool ext_phy = phy != &dev->phy;
+ u32 trb;
+
+ if (!phy->omac_mask)
+ return;
+
+ /* In rare cases, TRB pointers might be out of sync leads to RMAC
+ * stopping Rx, so check status periodically to see if TRB hardware
+ * requires minimal recovery.
+ */
+ trb = mt76_rr(dev, MT_TRB_RXPSR0(phy->band_idx));
+
+ if ((FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, trb) !=
+ FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, trb)) &&
+ (FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, phy->trb_ts) !=
+ FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, phy->trb_ts)) &&
+ trb == phy->trb_ts)
+ mt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L3_RX_ABORT,
+ ext_phy);
+
+ phy->trb_ts = trb;
+}
+
void mt7915_mac_sta_rc_work(struct work_struct *work)
{
struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work);
@@ -2356,6 +2479,7 @@ void mt7915_mac_work(struct work_struct *work)
mphy->mac_work_count = 0;
mt7915_mac_update_stats(phy);
+ mt7915_mac_severe_check(phy);
}
mutex_unlock(&mphy->dev->mutex);
@@ -2600,6 +2724,34 @@ static int mt7915_mac_check_twt_req(struct ieee80211_twt_setup *twt)
return 0;
}
+static bool
+mt7915_mac_twt_param_equal(struct mt7915_sta *msta,
+ struct ieee80211_twt_params *twt_agrt)
+{
+ u16 type = le16_to_cpu(twt_agrt->req_type);
+ u8 exp;
+ int i;
+
+ exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type);
+ for (i = 0; i < MT7915_MAX_STA_TWT_AGRT; i++) {
+ struct mt7915_twt_flow *f;
+
+ if (!(msta->twt.flowid_mask & BIT(i)))
+ continue;
+
+ f = &msta->twt.flow[i];
+ if (f->duration == twt_agrt->min_twt_dur &&
+ f->mantissa == twt_agrt->mantissa &&
+ f->exp == exp &&
+ f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) &&
+ f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) &&
+ f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER))
+ return true;
+ }
+
+ return false;
+}
+
void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct ieee80211_twt_setup *twt)
@@ -2625,6 +2777,12 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
goto unlock;
+ if (twt_agrt->min_twt_dur < MT7915_MIN_TWT_DUR) {
+ setup_cmd = TWT_SETUP_CMD_DICTATE;
+ twt_agrt->min_twt_dur = MT7915_MIN_TWT_DUR;
+ goto unlock;
+ }
+
flowid = ffs(~msta->twt.flowid_mask) - 1;
le16p_replace_bits(&twt_agrt->req_type, flowid,
IEEE80211_TWT_REQTYPE_FLOWID);
@@ -2633,6 +2791,9 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type);
sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type);
+ if (mt7915_mac_twt_param_equal(msta, twt_agrt))
+ goto unlock;
+
flow = &msta->twt.flow[flowid];
memset(flow, 0, sizeof(*flow));
INIT_LIST_HEAD(&flow->list);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h
index 5add1dd36dbe..c5fd1a618ae7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h
@@ -24,6 +24,7 @@ enum rx_pkt_type {
PKT_TYPE_TXRX_NOTIFY,
PKT_TYPE_RX_EVENT,
PKT_TYPE_RX_FW_MONITOR = 0x0c,
+ PKT_TYPE_TXRX_NOTIFY_V0 = 0x18,
};
/* RXD DW1 */
@@ -311,6 +312,7 @@ struct mt7915_tx_free {
#define MT_TX_FREE_VER GENMASK(18, 16)
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
+#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0)
#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
/* 0: success, others: dropped */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index c3f44d801e7f..710ca757fb52 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -42,10 +42,6 @@ static int mt7915_start(struct ieee80211_hw *hw)
if (ret)
goto out;
- ret = mt7915_mcu_set_scs(dev, 0, true);
- if (ret)
- goto out;
-
mt7915_mac_enable_nf(dev, 0);
}
@@ -58,10 +54,6 @@ static int mt7915_start(struct ieee80211_hw *hw)
if (ret)
goto out;
- ret = mt7915_mcu_set_scs(dev, 1, true);
- if (ret)
- goto out;
-
mt7915_mac_enable_nf(dev, 1);
}
@@ -174,14 +166,14 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)
for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) {
mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;
- mvif->bitrate_mask.control[i].he_gi = GENMASK(7, 0);
- mvif->bitrate_mask.control[i].he_ltf = GENMASK(7, 0);
+ mvif->bitrate_mask.control[i].he_gi = 0xff;
+ mvif->bitrate_mask.control[i].he_ltf = 0xff;
mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0);
- memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0),
+ memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff,
sizeof(mvif->bitrate_mask.control[i].ht_mcs));
- memset(mvif->bitrate_mask.control[i].vht_mcs, GENMASK(15, 0),
+ memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff,
sizeof(mvif->bitrate_mask.control[i].vht_mcs));
- memset(mvif->bitrate_mask.control[i].he_mcs, GENMASK(15, 0),
+ memset(mvif->bitrate_mask.control[i].he_mcs, 0xff,
sizeof(mvif->bitrate_mask.control[i].he_mcs));
}
}
@@ -204,8 +196,8 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
is_zero_ether_addr(vif->addr))
phy->monitor_vif = vif;
- mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1;
- if (mvif->mt76.idx >= MT7915_MAX_INTERFACES) {
+ mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);
+ if (mvif->mt76.idx >= (MT7915_MAX_INTERFACES << dev->dbdc_support)) {
ret = -ENOSPC;
goto out;
}
@@ -227,7 +219,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out;
- dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
+ dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
idx = MT7915_WTBL_RESERVED - mvif->mt76.idx;
@@ -246,7 +238,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
if (vif->txq) {
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
- mtxq->wcid = &mvif->sta.wcid;
+ mtxq->wcid = idx;
}
if (vif->type != NL80211_IFTYPE_AP &&
@@ -290,7 +282,7 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
mutex_lock(&dev->mt76.mutex);
- dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx);
+ dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mutex_unlock(&dev->mt76.mutex);
@@ -630,8 +622,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
mt7915_update_bss_color(hw, vif, &info->he_bss_color);
if (changed & (BSS_CHANGED_BEACON |
- BSS_CHANGED_BEACON_ENABLED))
- mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
+ BSS_CHANGED_BEACON_ENABLED |
+ BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
+ BSS_CHANGED_FILS_DISCOVERY))
+ mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);
mutex_unlock(&dev->mt76.mutex);
}
@@ -644,7 +638,7 @@ mt7915_channel_switch_beacon(struct ieee80211_hw *hw,
struct mt7915_dev *dev = mt7915_hw_dev(hw);
mutex_lock(&dev->mt76.mutex);
- mt7915_mcu_add_beacon(hw, vif, true);
+ mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON);
mutex_unlock(&dev->mt76.mutex);
}
@@ -1381,6 +1375,39 @@ out:
return ret;
}
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+static int
+mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct net_device_path_ctx *ctx,
+ struct net_device_path *path)
+{
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+
+ if (!mtk_wed_device_active(wed))
+ return -ENODEV;
+
+ if (msta->wcid.idx > 0xff)
+ return -EIO;
+
+ path->type = DEV_PATH_MTK_WDMA;
+ path->dev = ctx->dev;
+ path->mtk_wdma.wdma_idx = wed->wdma_idx;
+ path->mtk_wdma.bss = mvif->mt76.idx;
+ path->mtk_wdma.wcid = msta->wcid.idx;
+ path->mtk_wdma.queue = phy != &dev->phy;
+
+ ctx->dev = NULL;
+
+ return 0;
+}
+#endif
+
const struct ieee80211_ops mt7915_ops = {
.tx = mt7915_tx,
.start = mt7915_start,
@@ -1428,4 +1455,7 @@ const struct ieee80211_ops mt7915_ops = {
.sta_add_debugfs = mt7915_sta_add_debugfs,
#endif
.set_radar_background = mt7915_set_radar_background,
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ .net_fill_forward_path = mt7915_net_fill_forward_path,
+#endif
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index df31084e860f..b7e2b365356c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -1854,7 +1854,8 @@ mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
continue;
for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
- const u8 *data;
+ const struct ieee80211_bssid_index *idx;
+ const u8 *idx_ie;
if (sub_elem->id || sub_elem->datalen < 4)
continue; /* not a valid BSS profile */
@@ -1862,14 +1863,19 @@ mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
/* Find WLAN_EID_MULTI_BSSID_IDX
* in the merged nontransmitted profile
*/
- data = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
- sub_elem->data,
- sub_elem->datalen);
- if (!data || data[1] < 1 || !data[2])
+ idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
+ sub_elem->data,
+ sub_elem->datalen);
+ if (!idx_ie || idx_ie[1] < sizeof(*idx))
continue;
- mbss->offset[data[2]] = cpu_to_le16(data - skb->data);
- mbss->bitmap |= cpu_to_le32(BIT(data[2]));
+ idx = (void *)(idx_ie + 2);
+ if (!idx->bssid_index || idx->bssid_index > 31)
+ continue;
+
+ mbss->offset[idx->bssid_index] =
+ cpu_to_le16(idx_ie - skb->data);
+ mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index));
}
}
}
@@ -1886,6 +1892,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
u8 *buf;
int len = sizeof(*cont) + MT_TXD_SIZE + skb->len;
+ len = (len & 0x3) ? ((len | 0x3) + 1) : len;
tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT,
len, &bcn->sub_ntlv, &bcn->len);
@@ -1904,7 +1911,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
buf = (u8 *)tlv + sizeof(*cont);
mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
- true);
+ BSS_CHANGED_BEACON);
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
}
@@ -1986,8 +1993,71 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
}
}
-int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int en)
+static void
+mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+ struct sk_buff *rskb, struct bss_info_bcn *bcn,
+ u32 changed)
+{
+#define OFFLOAD_TX_MODE_SU BIT(0)
+#define OFFLOAD_TX_MODE_MU BIT(1)
+ struct ieee80211_hw *hw = mt76_hw(dev);
+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+ struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
+ enum nl80211_band band = chandef->chan->band;
+ struct mt76_wcid *wcid = &dev->mt76.global_wcid;
+ struct bss_info_inband_discovery *discov;
+ struct ieee80211_tx_info *info;
+ struct sk_buff *skb = NULL;
+ struct tlv *tlv;
+ bool ext_phy = phy != &dev->phy;
+ u8 *buf, interval;
+ int len;
+
+ if (changed & BSS_CHANGED_FILS_DISCOVERY &&
+ vif->bss_conf.fils_discovery.max_interval) {
+ interval = vif->bss_conf.fils_discovery.max_interval;
+ skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
+ } else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
+ vif->bss_conf.unsol_bcast_probe_resp_interval) {
+ interval = vif->bss_conf.unsol_bcast_probe_resp_interval;
+ skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
+ }
+
+ if (!skb)
+ return;
+
+ info = IEEE80211_SKB_CB(skb);
+ info->control.vif = vif;
+ info->band = band;
+
+ if (ext_phy)
+ info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
+
+ len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
+ len = (len & 0x3) ? ((len | 0x3) + 1) : len;
+
+ tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
+ len, &bcn->sub_ntlv, &bcn->len);
+ discov = (struct bss_info_inband_discovery *)tlv;
+ discov->tx_mode = OFFLOAD_TX_MODE_SU;
+ /* 0: UNSOL PROBE RESP, 1: FILS DISCOV */
+ discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
+ discov->tx_interval = interval;
+ discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
+ discov->enable = true;
+
+ buf = (u8 *)tlv + sizeof(*discov);
+
+ mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
+ changed);
+ memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
+
+ dev_kfree_skb(skb);
+}
+
+int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ int en, u32 changed)
{
#define MAX_BEACON_SIZE 512
struct mt7915_dev *dev = mt7915_hw_dev(hw);
@@ -2038,6 +2108,11 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
dev_kfree_skb(skb);
+ if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
+ changed & BSS_CHANGED_FILS_DISCOVERY)
+ mt7915_mcu_beacon_inband_discov(dev, vif, rskb,
+ bcn, changed);
+
out:
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
MCU_EXT_CMD(BSS_INFO_UPDATE), true);
@@ -2465,10 +2540,7 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
/* force firmware operation mode into normal state,
* which should be set before firmware download stage.
*/
- if (is_mt7915(&dev->mt76))
- mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
- else
- mt76_wr(dev, MT_SWDEF_MODE_MT7916, MT_SWDEF_NORMAL_MODE);
+ mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
ret = mt7915_driver_own(dev, 0);
if (ret)
@@ -2493,6 +2565,9 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
if (ret)
return ret;
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
+ mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
+
ret = mt7915_mcu_set_mwds(dev, 1);
if (ret)
return ret;
@@ -2583,22 +2658,6 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band,
&req_mac, sizeof(req_mac), true);
}
-int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable)
-{
- struct {
- __le32 cmd;
- u8 band;
- u8 enable;
- } __packed req = {
- .cmd = cpu_to_le32(SCS_ENABLE),
- .band = band,
- .enable = enable + 1,
- };
-
- return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SCS_CTRL), &req,
- sizeof(req), false);
-}
-
int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *param)
{
struct mt7915_mcu_tx *req = (struct mt7915_mcu_tx *)param;
@@ -3671,3 +3730,32 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TWT_AGRT_UPDATE),
&req, sizeof(req), true);
}
+
+int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
+{
+ struct {
+ __le32 idx;
+ __le32 ofs;
+ __le32 data;
+ } __packed req = {
+ .idx = cpu_to_le32(u32_get_bits(regidx, GENMASK(31, 28))),
+ .ofs = cpu_to_le32(u32_get_bits(regidx, GENMASK(27, 0))),
+ .data = set ? cpu_to_le32(*val) : 0,
+ };
+ struct sk_buff *skb;
+ int ret;
+
+ if (set)
+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_REG_ACCESS),
+ &req, sizeof(req), false);
+
+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(RF_REG_ACCESS),
+ &req, sizeof(req), true, &skb);
+ if (ret)
+ return ret;
+
+ *val = le32_to_cpu(*(__le32 *)(skb->data + 8));
+ dev_kfree_skb(skb);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 960072a44222..5abde482a97f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -304,16 +304,6 @@ enum mcu_mmps_mode {
MCU_MMPS_DISABLE,
};
-enum {
- SCS_SEND_DATA,
- SCS_SET_MANUAL_PD_TH,
- SCS_CONFIG,
- SCS_ENABLE,
- SCS_SHOW_INFO,
- SCS_GET_GLO_ADDR,
- SCS_GET_GLO_ADDR_EVENT,
-};
-
struct bss_info_bmc_rate {
__le16 tag;
__le16 len;
@@ -414,11 +404,23 @@ struct bss_info_bcn_cont {
__le16 pkt_len;
} __packed __aligned(4);
+struct bss_info_inband_discovery {
+ __le16 tag;
+ __le16 len;
+ u8 tx_type;
+ u8 tx_mode;
+ u8 tx_interval;
+ u8 enable;
+ __le16 rsv;
+ __le16 prob_rsp_len;
+} __packed __aligned(4);
+
enum {
BSS_INFO_BCN_CSA,
BSS_INFO_BCN_BCC,
BSS_INFO_BCN_MBSSID,
BSS_INFO_BCN_CONTENT,
+ BSS_INFO_BCN_DISCOV,
BSS_INFO_BCN_MAX
};
@@ -473,6 +475,20 @@ enum {
MURU_GET_TXC_TX_STATS = 151,
};
+enum {
+ SER_QUERY,
+ /* recovery */
+ SER_SET_RECOVER_L1,
+ SER_SET_RECOVER_L2,
+ SER_SET_RECOVER_L3_RX_ABORT,
+ SER_SET_RECOVER_L3_TX_ABORT,
+ SER_SET_RECOVER_L3_TX_DISABLE,
+ SER_SET_RECOVER_L3_BF,
+ /* action */
+ SER_ENABLE = 2,
+ SER_RECOVER
+};
+
#define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct bss_info_omac) + \
sizeof(struct bss_info_basic) +\
@@ -486,6 +502,7 @@ enum {
#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct bss_info_bcn_cntdwn) + \
sizeof(struct bss_info_bcn_mbss) + \
- sizeof(struct bss_info_bcn_cont))
+ sizeof(struct bss_info_bcn_cont) + \
+ sizeof(struct bss_info_inband_discovery))
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
index 5062e0d8cae4..46ee8a7db7bc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
@@ -22,6 +22,8 @@ static const u32 mt7915_reg[] = {
[WFDMA_EXT_CSR_ADDR] = 0xd7000,
[CBTOP1_PHY_END] = 0x77ffffff,
[INFRA_MCU_ADDR_END] = 0x7c3fffff,
+ [FW_EXCEPTION_ADDR] = 0x219848,
+ [SWDEF_BASE_ADDR] = 0x41f200,
};
static const u32 mt7916_reg[] = {
@@ -36,6 +38,8 @@ static const u32 mt7916_reg[] = {
[WFDMA_EXT_CSR_ADDR] = 0xd7000,
[CBTOP1_PHY_END] = 0x7fffffff,
[INFRA_MCU_ADDR_END] = 0x7c085fff,
+ [FW_EXCEPTION_ADDR] = 0x022050bc,
+ [SWDEF_BASE_ADDR] = 0x411400,
};
static const u32 mt7986_reg[] = {
@@ -50,6 +54,8 @@ static const u32 mt7986_reg[] = {
[WFDMA_EXT_CSR_ADDR] = 0x27000,
[CBTOP1_PHY_END] = 0x7fffffff,
[INFRA_MCU_ADDR_END] = 0x7c085fff,
+ [FW_EXCEPTION_ADDR] = 0x02204ffc,
+ [SWDEF_BASE_ADDR] = 0x411400,
};
static const u32 mt7915_offs[] = {
@@ -547,15 +553,21 @@ static void mt7915_rx_poll_complete(struct mt76_dev *mdev,
static void mt7915_irq_tasklet(struct tasklet_struct *t)
{
struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet);
+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
u32 intr, intr1, mask;
- mt76_wr(dev, MT_INT_MASK_CSR, 0);
- if (dev->hif2)
- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+ if (mtk_wed_device_active(wed)) {
+ mtk_wed_device_irq_set_mask(wed, 0);
+ intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask);
+ } else {
+ mt76_wr(dev, MT_INT_MASK_CSR, 0);
+ if (dev->hif2)
+ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
- intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
- intr &= dev->mt76.mmio.irqmask;
- mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
+ intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
+ intr &= dev->mt76.mmio.irqmask;
+ mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
+ }
if (dev->hif2) {
intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
@@ -601,7 +613,7 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
mt76_wr(dev, MT_MCU_CMD, val);
if (val & MT_MCU_CMD_ERROR_MASK) {
dev->reset_state = val;
- ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
+ queue_work(dev->mt76.wq, &dev->reset_work);
wake_up(&dev->reset_wait);
}
}
@@ -610,10 +622,15 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
{
struct mt7915_dev *dev = dev_instance;
+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
- mt76_wr(dev, MT_INT_MASK_CSR, 0);
- if (dev->hif2)
- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+ if (mtk_wed_device_active(wed)) {
+ mtk_wed_device_irq_set_mask(wed, 0);
+ } else {
+ mt76_wr(dev, MT_INT_MASK_CSR, 0);
+ if (dev->hif2)
+ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
+ }
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
@@ -665,8 +682,6 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet);
- mt76_wr(dev, MT_INT_MASK_CSR, 0);
-
return dev;
error:
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 6efa0a2e2345..4dcae6991669 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -66,6 +66,7 @@
#define MT7915_MAX_TWT_AGRT 16
#define MT7915_MAX_STA_TWT_AGRT 8
+#define MT7915_MIN_TWT_DUR 64
#define MT7915_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 2)
struct mt7915_vif;
@@ -247,6 +248,8 @@ struct mt7915_phy {
u8 rdd_state;
+ u32 trb_ts;
+
u32 rx_ampdu_ts;
u32 ampdu_ref;
@@ -309,9 +312,6 @@ struct mt7915_dev {
bool flash_mode;
bool muru_debug;
bool ibf;
- u8 fw_debug_wm;
- u8 fw_debug_wa;
- u8 fw_debug_bin;
struct dentry *debugfs_dir;
struct rchan *relay_fwlog;
@@ -319,7 +319,13 @@ struct mt7915_dev {
void *cal;
struct {
- u8 table_mask;
+ u8 debug_wm;
+ u8 debug_wa;
+ u8 debug_bin;
+ } fw;
+
+ struct {
+ u16 table_mask;
u8 n_agrt;
} twt;
@@ -429,8 +435,11 @@ static inline void mt7986_wmac_disable(struct mt7915_dev *dev)
#endif
struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
void __iomem *mem_base, u32 device_id);
+void mt7915_wfsys_reset(struct mt7915_dev *dev);
irqreturn_t mt7915_irq_handler(int irq, void *dev_instance);
u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif);
+u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
+
int mt7915_register_device(struct mt7915_dev *dev);
void mt7915_unregister_device(struct mt7915_dev *dev);
int mt7915_eeprom_init(struct mt7915_dev *dev);
@@ -440,7 +449,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
struct ieee80211_channel *chan,
u8 chain_idx);
s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band);
-int mt7915_dma_init(struct mt7915_dev *dev);
+int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2);
void mt7915_dma_prefetch(struct mt7915_dev *dev);
void mt7915_dma_cleanup(struct mt7915_dev *dev);
int mt7915_mcu_init(struct mt7915_dev *dev);
@@ -463,7 +472,7 @@ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,
int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
struct cfg80211_he_bss_color *he_bss_color);
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- int enable);
+ int enable, u32 changed);
int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
@@ -485,7 +494,6 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
bool hdr_trans);
int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode,
u8 en);
-int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable);
int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band);
int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable);
int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
@@ -506,6 +514,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct rate_info *rate);
int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
struct cfg80211_chan_def *chandef);
+int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set);
int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
@@ -550,7 +559,7 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy);
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
- struct ieee80211_key_conf *key, bool beacon);
+ struct ieee80211_key_conf *key, u32 changed);
void mt7915_mac_set_timing(struct mt7915_phy *phy);
int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
@@ -572,7 +581,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct mt76_tx_info *tx_info);
void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt7915_tx_token_put(struct mt7915_dev *dev);
-int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base);
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);
bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
index 6f819c41a4c4..d74f609775d3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
@@ -12,6 +12,9 @@
#include "mac.h"
#include "../trace.h"
+static bool wed_enable = false;
+module_param(wed_enable, bool, 0644);
+
static LIST_HEAD(hif_list);
static DEFINE_SPINLOCK(hif_lock);
static u32 hif_idx;
@@ -92,12 +95,79 @@ static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
return 0;
}
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+static int mt7915_wed_offload_enable(struct mtk_wed_device *wed)
+{
+ struct mt7915_dev *dev;
+ int ret;
+
+ dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
+
+ spin_lock_bh(&dev->mt76.token_lock);
+ dev->mt76.token_size = wed->wlan.token_start;
+ spin_unlock_bh(&dev->mt76.token_lock);
+
+ ret = wait_event_timeout(dev->mt76.tx_wait,
+ !dev->mt76.wed_token_count, HZ);
+ if (!ret)
+ return -EAGAIN;
+
+ return 0;
+}
+
+static void mt7915_wed_offload_disable(struct mtk_wed_device *wed)
+{
+ struct mt7915_dev *dev;
+
+ dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
+
+ spin_lock_bh(&dev->mt76.token_lock);
+ dev->mt76.token_size = MT7915_TOKEN_SIZE;
+ spin_unlock_bh(&dev->mt76.token_lock);
+}
+#endif
+
+static int
+mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq)
+{
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+ int ret;
+
+ if (!wed_enable)
+ return 0;
+
+ wed->wlan.pci_dev = pdev;
+ wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) +
+ MT_WFDMA_EXT_CSR_BASE;
+ wed->wlan.nbuf = 4096;
+ wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
+ wed->wlan.init_buf = mt7915_wed_init_buf;
+ wed->wlan.offload_enable = mt7915_wed_offload_enable;
+ wed->wlan.offload_disable = mt7915_wed_offload_disable;
+
+ if (mtk_wed_device_attach(wed) != 0)
+ return 0;
+
+ *irq = wed->irq;
+ dev->mt76.dma_dev = wed->dev;
+
+ ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ return 1;
+#else
+ return 0;
+#endif
+}
+
static int mt7915_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
+ struct mt7915_hif *hif2 = NULL;
struct mt7915_dev *dev;
struct mt76_dev *mdev;
- struct mt7915_hif *hif2;
int irq;
int ret;
@@ -126,19 +196,27 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
return PTR_ERR(dev);
mdev = &dev->mt76;
+ mt7915_wfsys_reset(dev);
hif2 = mt7915_pci_init_hif2(pdev);
- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+ ret = mt7915_pci_wed_init(dev, pdev, &irq);
if (ret < 0)
- goto free_device;
+ goto free_wed_or_irq_vector;
+
+ if (!ret) {
+ hif2 = mt7915_pci_init_hif2(pdev);
+
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+ if (ret < 0)
+ goto free_device;
+
+ irq = pdev->irq;
+ }
- irq = pdev->irq;
ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
- goto free_irq_vector;
-
- mt76_wr(dev, MT_INT_MASK_CSR, 0);
+ goto free_wed_or_irq_vector;
/* master switch of PCIe tnterrupt enable */
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
@@ -173,8 +251,11 @@ free_hif2:
if (dev->hif2)
put_device(dev->hif2->dev);
devm_free_irq(mdev->dev, irq, dev);
-free_irq_vector:
- pci_free_irq_vectors(pdev);
+free_wed_or_irq_vector:
+ if (mtk_wed_device_active(&mdev->mmio.wed))
+ mtk_wed_device_detach(&mdev->mmio.wed);
+ else
+ pci_free_irq_vectors(pdev);
free_device:
mt76_free_device(&dev->mt76);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
index e5f93c40591c..4953be208c5e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
@@ -30,6 +30,8 @@ enum reg_rev {
WFDMA_EXT_CSR_ADDR,
CBTOP1_PHY_END,
INFRA_MCU_ADDR_END,
+ FW_EXCEPTION_ADDR,
+ SWDEF_BASE_ADDR,
__MT_REG_MAX,
};
@@ -158,6 +160,9 @@ enum offs_rev {
#define MT_MDP_DCR1 MT_MDP(0x004)
#define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3)
+#define MT_MDP_DCR2 MT_MDP(0x0e8)
+#define MT_MDP_DCR2_RX_TRANS_SHORT BIT(2)
+
#define MT_MDP_BNRCFR0(_band) MT_MDP(__OFFS(MDP_BNRCFR0) + \
((_band) << 8))
#define MT_MDP_RCFR0_MCU_RX_MGMT GENMASK(5, 4)
@@ -172,6 +177,14 @@ enum offs_rev {
#define MT_MDP_TO_HIF 0
#define MT_MDP_TO_WM 1
+/* TRB: band 0(0x820e1000), band 1(0x820f1000) */
+#define MT_WF_TRB_BASE(_band) ((_band) ? 0x820f1000 : 0x820e1000)
+#define MT_WF_TRB(_band, ofs) (MT_WF_TRB_BASE(_band) + (ofs))
+
+#define MT_TRB_RXPSR0(_band) MT_WF_TRB(_band, 0x03c)
+#define MT_TRB_RXPSR0_RX_WTBL_PTR GENMASK(25, 16)
+#define MT_TRB_RXPSR0_RX_RMAC_PTR GENMASK(9, 0)
+
/* TMAC: band 0(0x820e4000), band 1(0x820f4000) */
#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000)
#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))
@@ -565,18 +578,31 @@ enum offs_rev {
/* WFDMA CSR */
#define MT_WFDMA_EXT_CSR_BASE __REG(WFDMA_EXT_CSR_ADDR)
+#define MT_WFDMA_EXT_CSR_PHYS_BASE 0x18027000
#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs))
+#define MT_WFDMA_EXT_CSR_PHYS(ofs) (MT_WFDMA_EXT_CSR_PHYS_BASE + (ofs))
-#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30)
+#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR_PHYS(0x30)
#define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0)
+#define MT_WFDMA_HOST_CONFIG_WED BIT(1)
-#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
+#define MT_WFDMA_WED_RING_CONTROL MT_WFDMA_EXT_CSR_PHYS(0x34)
+#define MT_WFDMA_WED_RING_CONTROL_TX0 GENMASK(4, 0)
+#define MT_WFDMA_WED_RING_CONTROL_TX1 GENMASK(12, 8)
+#define MT_WFDMA_WED_RING_CONTROL_RX1 GENMASK(20, 16)
+
+#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR_PHYS(0x44)
#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
#define MT_PCIE_RECOG_ID 0xd7090
#define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0)
#define MT_PCIE_RECOG_ID_SEM BIT(31)
+#define MT_INT_WED_MASK_CSR MT_WFDMA_EXT_CSR(0x204)
+
+#define MT_WED_TX_RING_BASE MT_WFDMA_EXT_CSR(0x300)
+#define MT_WED_RX_RING_BASE MT_WFDMA_EXT_CSR(0x400)
+
/* WFDMA0 PCIE1 */
#define MT_WFDMA0_PCIE1_BASE __REG(WFDMA0_PCIE1_ADDR)
#define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs))
@@ -794,6 +820,7 @@ enum offs_rev {
/* ADIE */
#define MT_ADIE_CHIP_ID 0x02c
+#define MT_ADIE_VERSION_MASK GENMASK(15, 0)
#define MT_ADIE_CHIP_ID_MASK GENMASK(31, 16)
#define MT_ADIE_IDX0 GENMASK(15, 0)
#define MT_ADIE_IDX1 GENMASK(31, 16)
@@ -913,12 +940,27 @@ enum offs_rev {
#define MT_ADIE_TYPE_MASK BIT(1)
/* FW MODE SYNC */
-#define MT_SWDEF_MODE 0x41f23c
-#define MT_SWDEF_MODE_MT7916 0x41143c
+#define MT_FW_EXCEPTION __REG(FW_EXCEPTION_ADDR)
+
+#define MT_SWDEF_BASE __REG(SWDEF_BASE_ADDR)
+
+#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
+#define MT_SWDEF_MODE MT_SWDEF(0x3c)
#define MT_SWDEF_NORMAL_MODE 0
#define MT_SWDEF_ICAP_MODE 1
#define MT_SWDEF_SPECTRUM_MODE 2
+#define MT_SWDEF_SER_STATS MT_SWDEF(0x040)
+#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044)
+#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048)
+#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04C)
+#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050)
+#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054)
+#define MT_SWDEF_LAMC_WISR6_BN0_STATS MT_SWDEF(0x058)
+#define MT_SWDEF_LAMC_WISR6_BN1_STATS MT_SWDEF(0x05C)
+#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x060)
+#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x064)
+
#define MT_DIC_CMD_REG_BASE 0x41f000
#define MT_DIC_CMD_REG(ofs) (MT_DIC_CMD_REG_BASE + (ofs))
#define MT_DIC_CMD_REG_CMD MT_DIC_CMD_REG(0x10)
@@ -965,10 +1007,6 @@ enum offs_rev {
#define MT_TOP_MISC MT_TOP(0xf0)
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
-#define MT_HW_BOUND 0x70010020
-#define MT_HW_REV 0x70010204
-#define MT_WF_SUBSYS_RST 0x70002600
-
#define MT_TOP_WFSYS_WAKEUP MT_TOP(0x1a4)
#define MT_TOP_WFSYS_WAKEUP_MASK BIT(0)
@@ -1030,6 +1068,10 @@ enum offs_rev {
#define MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK BIT(3)
#define MT_MCU_BUS_DBG_TIMEOUT_EN_MASK BIT(2)
+#define MT_HW_BOUND 0x70010020
+#define MT_HW_REV 0x70010204
+#define MT_WF_SUBSYS_RST 0x70002600
+
/* PCIE MAC */
#define MT_PCIE_MAC_BASE 0x74030000
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
@@ -1038,6 +1080,9 @@ enum offs_rev {
#define MT_PCIE1_MAC_INT_ENABLE 0x74020188
#define MT_PCIE1_MAC_INT_ENABLE_MT7916 0x74090188
+#define MT_WM_MCU_PC 0x7c060204
+#define MT_WA_MCU_PC 0x7c06020c
+
/* PP TOP */
#define MT_WF_PP_TOP_BASE 0x820cc000
#define MT_WF_PP_TOP(ofs) (MT_WF_PP_TOP_BASE + (ofs))
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
index 3028c02cb840..c74afa746251 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c
@@ -12,6 +12,7 @@
#include <linux/iopoll.h>
#include <linux/reset.h>
#include <linux/of_net.h>
+#include <linux/clk.h>
#include "mt7915.h"
@@ -210,6 +211,8 @@ static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev)
if (IS_ERR_OR_NULL(state))
return -EINVAL;
break;
+ default:
+ return -EINVAL;
}
ret = pinctrl_select_state(pinctrl, state);
@@ -468,17 +471,32 @@ static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie)
static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
{
+ u32 id, version, rg_xo_01, rg_xo_03;
int ret;
+ ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_CHIP_ID, &id);
+ if (ret)
+ return ret;
+
+ version = FIELD_GET(MT_ADIE_VERSION_MASK, id);
+
ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_TOP_THADC, 0x4a563b00);
if (ret)
return ret;
- ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, 0x1d59080f);
+ if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) {
+ rg_xo_01 = 0x1d59080f;
+ rg_xo_03 = 0x34c00fe0;
+ } else {
+ rg_xo_01 = 0x1959f80f;
+ rg_xo_03 = 0x34d00fe0;
+ }
+
+ ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, rg_xo_01);
if (ret)
return ret;
- return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, 0x34c00fe0);
+ return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, rg_xo_03);
}
static int
@@ -1115,6 +1133,19 @@ static int mt7986_wmac_init(struct mt7915_dev *dev)
{
struct device *pdev = dev->mt76.dev;
struct platform_device *pfdev = to_platform_device(pdev);
+ struct clk *mcu_clk, *ap_conn_clk;
+
+ mcu_clk = devm_clk_get(pdev, "mcu");
+ if (IS_ERR(mcu_clk))
+ dev_err(pdev, "mcu clock not found\n");
+ else if (clk_prepare_enable(mcu_clk))
+ dev_err(pdev, "mcu clock configuration failed\n");
+
+ ap_conn_clk = devm_clk_get(pdev, "ap2conn");
+ if (IS_ERR(ap_conn_clk))
+ dev_err(pdev, "ap2conn clock not found\n");
+ else if (clk_prepare_enable(ap_conn_clk))
+ dev_err(pdev, "ap2conn clock configuration failed\n");
dev->dcm = devm_platform_ioremap_resource(pfdev, 1);
if (IS_ERR(dev->dcm))
@@ -1128,7 +1159,7 @@ static int mt7986_wmac_init(struct mt7915_dev *dev)
if (IS_ERR(dev->rstc))
return PTR_ERR(dev->rstc);
- return mt7986_wmac_enable(dev);
+ return 0;
}
static int mt7986_wmac_probe(struct platform_device *pdev)
@@ -1161,12 +1192,12 @@ static int mt7986_wmac_probe(struct platform_device *pdev)
if (ret)
goto free_device;
- mt76_wr(dev, MT_INT_MASK_CSR, 0);
-
ret = mt7986_wmac_init(dev);
if (ret)
goto free_irq;
+ mt7915_wfsys_reset(dev);
+
ret = mt7915_register_device(dev);
if (ret)
goto free_irq;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
index ca7e20fb5fc0..3a6b158b779e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
@@ -9,7 +9,7 @@ static int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc)
{
int i, err;
- err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE);
+ err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE, 0);
if (err < 0)
return err;
@@ -296,8 +296,8 @@ int mt7921_dma_init(struct mt7921_dev *dev)
if (ret < 0)
return ret;
- netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
- mt7921_poll_tx, NAPI_POLL_WEIGHT);
+ netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
+ mt7921_poll_tx);
napi_enable(&dev->mt76.tx_napi);
return mt7921_dma_enable(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index 91fc41922d95..4a8675634f80 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -11,6 +11,10 @@ static const struct ieee80211_iface_limit if_limits[] = {
{
.max = MT7921_MAX_INTERFACES,
.types = BIT(NL80211_IFTYPE_STATION)
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_AP)
}
};
@@ -64,7 +68,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
wiphy->iface_combinations = if_comb;
wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
WIPHY_FLAG_4ADDR_STATION);
- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP);
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
wiphy->max_scan_ssids = 4;
@@ -80,6 +85,10 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
@@ -255,6 +264,10 @@ int mt7921_register_device(struct mt7921_dev *dev)
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work);
INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work);
INIT_DELAYED_WORK(&dev->coredump.work, mt7921_coredump_work);
+#if IS_ENABLED(CONFIG_IPV6)
+ INIT_WORK(&dev->ipv6_ns_work, mt7921_set_ipv6_ns_work);
+ skb_queue_head_init(&dev->ipv6_ns_list);
+#endif
skb_queue_head_init(&dev->phy.scan_event_list);
skb_queue_head_init(&dev->coredump.msg_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index b67615487910..a630ddbf19e5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -696,7 +696,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
status->nss =
FIELD_GET(MT_PRXV_NSTS, v0) + 1;
status->encoding = RX_ENC_VHT;
- if (i > 9)
+ if (i > 11)
return -EINVAL;
break;
case MT_PHY_TYPE_HE_MU:
@@ -814,6 +814,7 @@ mt7921_mac_write_txwi_8023(struct mt7921_dev *dev, __le32 *txwi,
{
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
u8 fc_type, fc_stype;
+ u16 ethertype;
bool wmm = false;
u32 val;
@@ -827,7 +828,8 @@ mt7921_mac_write_txwi_8023(struct mt7921_dev *dev, __le32 *txwi,
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
FIELD_PREP(MT_TXD1_TID, tid);
- if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN)
+ ethertype = get_unaligned_be16(&skb->data[12]);
+ if (ethertype >= ETH_P_802_3_MIN)
val |= MT_TXD1_ETH_802_3;
txwi[1] |= cpu_to_le32(val);
@@ -1361,12 +1363,21 @@ mt7921_vif_connect_iter(void *priv, u8 *mac,
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt7921_dev *dev = mvif->phy->dev;
+ struct ieee80211_hw *hw = mt76_hw(dev);
if (vif->type == NL80211_IFTYPE_STATION)
ieee80211_disconnect(vif, true);
mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true);
mt7921_mcu_set_tx(dev, vif);
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.wcid,
+ true);
+ mt7921_mcu_sta_update(dev, NULL, vif, true,
+ MT76_STA_INFO_STATE_NONE);
+ mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true);
+ }
}
/* system error recovery */
@@ -1715,3 +1726,29 @@ bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)
return false;
}
EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data);
+
+#if IS_ENABLED(CONFIG_IPV6)
+void mt7921_set_ipv6_ns_work(struct work_struct *work)
+{
+ struct mt7921_dev *dev = container_of(work, struct mt7921_dev,
+ ipv6_ns_work);
+ struct sk_buff *skb;
+ int ret = 0;
+
+ do {
+ skb = skb_dequeue(&dev->ipv6_ns_list);
+
+ if (!skb)
+ break;
+
+ mt7921_mutex_acquire(dev);
+ ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ MCU_UNI_CMD(OFFLOAD), true);
+ mt7921_mutex_release(dev);
+
+ } while (!ret);
+
+ if (ret)
+ skb_queue_purge(&dev->ipv6_ns_list);
+}
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index fdaf2451bc1d..80279f342109 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -5,6 +5,7 @@
#include <linux/platform_device.h>
#include <linux/pci.h>
#include <linux/module.h>
+#include <net/ipv6.h>
#include "mt7921.h"
#include "mcu.h"
@@ -12,7 +13,7 @@ static void
mt7921_gen_ppe_thresh(u8 *he_ppet, int nss)
{
u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
- u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
+ static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) |
FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK,
@@ -53,6 +54,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
switch (i) {
case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_AP:
break;
default:
continue;
@@ -86,6 +88,23 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
switch (i) {
+ case NL80211_IFTYPE_AP:
+ he_cap_elem->mac_cap_info[2] |=
+ IEEE80211_HE_MAC_CAP2_BSR;
+ he_cap_elem->mac_cap_info[4] |=
+ IEEE80211_HE_MAC_CAP4_BQR;
+ he_cap_elem->mac_cap_info[5] |=
+ IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX;
+ he_cap_elem->phy_cap_info[3] |=
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
+ IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
+ he_cap_elem->phy_cap_info[6] |=
+ IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
+ IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
+ he_cap_elem->phy_cap_info[9] |=
+ IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
+ IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
+ break;
case NL80211_IFTYPE_STATION:
he_cap_elem->mac_cap_info[1] |=
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
@@ -294,7 +313,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
mt7921_mutex_acquire(dev);
- mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1;
+ mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);
if (mvif->mt76.idx >= MT7921_MAX_INTERFACES) {
ret = -ENOSPC;
goto out;
@@ -310,7 +329,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out;
- dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
+ dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
idx = MT7921_WTBL_RESERVED - mvif->mt76.idx;
@@ -330,7 +349,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
if (vif->txq) {
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
- mtxq->wcid = &mvif->sta.wcid;
+ mtxq->wcid = idx;
}
out:
@@ -354,7 +373,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
- dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx);
+ dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mt7921_mutex_release(dev);
@@ -489,8 +508,8 @@ mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
mt7921_mcu_set_sniffer(dev, vif, monitor);
- pm->enable = !monitor;
- pm->ds_enable = !monitor;
+ pm->enable = pm->enable_user && !monitor;
+ pm->ds_enable = pm->ds_enable_user && !monitor;
mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
@@ -566,7 +585,6 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
u64 multicast)
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);
- struct mt7921_phy *phy = mt7921_hw_phy(hw);
u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
MT_WF_RFCR1_DROP_BF_POLL |
MT_WF_RFCR1_DROP_BA |
@@ -576,23 +594,23 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
#define MT76_FILTER(_flag, _hw) do { \
flags |= *total_flags & FIF_##_flag; \
- phy->rxfilter &= ~(_hw); \
- phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \
+ dev->mt76.rxfilter &= ~(_hw); \
+ dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \
} while (0)
mt7921_mutex_acquire(dev);
- phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
- MT_WF_RFCR_DROP_OTHER_BEACON |
- MT_WF_RFCR_DROP_FRAME_REPORT |
- MT_WF_RFCR_DROP_PROBEREQ |
- MT_WF_RFCR_DROP_MCAST_FILTERED |
- MT_WF_RFCR_DROP_MCAST |
- MT_WF_RFCR_DROP_BCAST |
- MT_WF_RFCR_DROP_DUPLICATE |
- MT_WF_RFCR_DROP_A2_BSSID |
- MT_WF_RFCR_DROP_UNWANTED_CTL |
- MT_WF_RFCR_DROP_STBC_MULTI);
+ dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
+ MT_WF_RFCR_DROP_OTHER_BEACON |
+ MT_WF_RFCR_DROP_FRAME_REPORT |
+ MT_WF_RFCR_DROP_PROBEREQ |
+ MT_WF_RFCR_DROP_MCAST_FILTERED |
+ MT_WF_RFCR_DROP_MCAST |
+ MT_WF_RFCR_DROP_BCAST |
+ MT_WF_RFCR_DROP_DUPLICATE |
+ MT_WF_RFCR_DROP_A2_BSSID |
+ MT_WF_RFCR_DROP_UNWANTED_CTL |
+ MT_WF_RFCR_DROP_STBC_MULTI);
MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |
MT_WF_RFCR_DROP_A3_MAC |
@@ -606,7 +624,7 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
MT_WF_RFCR_DROP_NDPA);
*total_flags = flags;
- mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter);
+ mt76_wr(dev, MT_WF_RFCR(0), dev->mt76.rxfilter);
if (*total_flags & FIF_CONTROL)
mt76_clear(dev, MT_WF_RFCR1(0), ctl_flags);
@@ -635,6 +653,20 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
}
}
+ if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
+ struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+
+ mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
+ true);
+ mt7921_mcu_sta_update(dev, NULL, vif, true,
+ MT76_STA_INFO_STATE_NONE);
+ }
+
+ if (changed & (BSS_CHANGED_BEACON |
+ BSS_CHANGED_BEACON_ENABLED))
+ mt7921_mcu_uni_add_beacon_offload(dev, hw, vif,
+ info->enable_beacon);
+
/* ensure that enable txcmd_mode after bss_info */
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
mt7921_mcu_set_tx(dev, vif);
@@ -1301,7 +1333,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw,
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
- mt76_connac_mcu_set_suspend_iter,
+ mt7921_mcu_set_suspend_iter,
&dev->mphy);
mt7921_mutex_release(dev);
@@ -1376,6 +1408,67 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw,
MCU_UNI_CMD(STA_REC_UPDATE));
}
+#if IS_ENABLED(CONFIG_IPV6)
+static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct inet6_dev *idev)
+{
+ struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+ struct mt7921_dev *dev = mvif->phy->dev;
+ struct inet6_ifaddr *ifa;
+ struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
+ struct sk_buff *skb;
+ u8 i, idx = 0;
+
+ struct {
+ struct {
+ u8 bss_idx;
+ u8 pad[3];
+ } __packed hdr;
+ struct mt76_connac_arpns_tlv arpns;
+ } req_hdr = {
+ .hdr = {
+ .bss_idx = mvif->mt76.idx,
+ },
+ .arpns = {
+ .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND),
+ .mode = 2, /* update */
+ .option = 1, /* update only */
+ },
+ };
+
+ read_lock_bh(&idev->lock);
+ list_for_each_entry(ifa, &idev->addr_list, if_list) {
+ if (ifa->flags & IFA_F_TENTATIVE)
+ continue;
+ ns_addrs[idx] = ifa->addr;
+ if (++idx >= IEEE80211_BSS_ARP_ADDR_LIST_LEN)
+ break;
+ }
+ read_unlock_bh(&idev->lock);
+
+ if (!idx)
+ return;
+
+ skb = __mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) +
+ idx * sizeof(struct in6_addr), GFP_ATOMIC);
+ if (!skb)
+ return;
+
+ req_hdr.arpns.ips_num = idx;
+ req_hdr.arpns.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)
+ + idx * sizeof(struct in6_addr));
+ skb_put_data(skb, &req_hdr, sizeof(req_hdr));
+
+ for (i = 0; i < idx; i++)
+ skb_put_data(skb, &ns_addrs[i].in6_u, sizeof(struct in6_addr));
+
+ skb_queue_tail(&dev->ipv6_ns_list, skb);
+
+ ieee80211_queue_work(dev->mt76.hw, &dev->ipv6_ns_work);
+}
+#endif
+
static int mt7921_set_sar_specs(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar)
{
@@ -1395,6 +1488,18 @@ out:
return err;
}
+static void
+mt7921_channel_switch_beacon(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_chan_def *chandef)
+{
+ struct mt7921_dev *dev = mt7921_hw_dev(hw);
+
+ mt7921_mutex_acquire(dev);
+ mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true);
+ mt7921_mutex_release(dev);
+}
+
const struct ieee80211_ops mt7921_ops = {
.tx = mt7921_tx,
.start = mt7921_start,
@@ -1409,10 +1514,14 @@ const struct ieee80211_ops mt7921_ops = {
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
.set_key = mt7921_set_key,
.sta_set_decap_offload = mt7921_sta_set_decap_offload,
+#if IS_ENABLED(CONFIG_IPV6)
+ .ipv6_addr_change = mt7921_ipv6_addr_change,
+#endif /* CONFIG_IPV6 */
.ampdu_action = mt7921_ampdu_action,
.set_rts_threshold = mt7921_set_rts_threshold,
.wake_tx_queue = mt76_wake_tx_queue,
.release_buffered_frames = mt76_release_buffered_frames,
+ .channel_switch_beacon = mt7921_channel_switch_beacon,
.get_txpower = mt76_get_txpower,
.get_stats = mt7921_get_stats,
.get_et_sset_count = mt7921_get_et_sset_count,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index da2be050ed7c..12bab18c4171 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -224,6 +224,49 @@ exit:
}
EXPORT_SYMBOL_GPL(mt7921_mcu_fill_message);
+#ifdef CONFIG_PM
+
+static int
+mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev,
+ struct ieee80211_vif *vif, bool suspend)
+{
+ struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+ struct {
+ struct {
+ u8 bss_idx;
+ u8 pad[3];
+ } __packed hdr;
+ struct mt76_connac_arpns_tlv arpns;
+ } req = {
+ .hdr = {
+ .bss_idx = mvif->mt76.idx,
+ },
+ .arpns = {
+ .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND),
+ .len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)),
+ .mode = suspend,
+ },
+ };
+
+ return mt76_mcu_send_msg(dev, MCU_UNI_CMD_OFFLOAD, &req, sizeof(req),
+ true);
+}
+
+void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+ if (IS_ENABLED(CONFIG_IPV6)) {
+ struct mt76_phy *phy = priv;
+
+ mt7921_mcu_set_ipv6_ns_filter(phy->dev, vif,
+ !test_bit(MT76_STATE_RUNNING,
+ &phy->state));
+ }
+
+ mt76_connac_mcu_set_suspend_iter(priv, mac, vif);
+}
+
+#endif /* CONFIG_PM */
+
static void
mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb)
{
@@ -248,7 +291,8 @@ mt7921_mcu_connection_loss_iter(void *priv, u8 *mac,
if (mvif->idx != event->bss_idx)
return;
- if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER))
+ if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER) ||
+ vif->type != NL80211_IFTYPE_STATION)
return;
ieee80211_connection_loss(vif);
@@ -1166,3 +1210,79 @@ int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req),
true);
}
+
+int
+mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
+ struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ bool enable)
+{
+ struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+ struct mt76_wcid *wcid = &dev->mt76.global_wcid;
+ struct ieee80211_mutable_offsets offs;
+ struct {
+ struct req_hdr {
+ u8 bss_idx;
+ u8 pad[3];
+ } __packed hdr;
+ struct bcn_content_tlv {
+ __le16 tag;
+ __le16 len;
+ __le16 tim_ie_pos;
+ __le16 csa_ie_pos;
+ __le16 bcc_ie_pos;
+ /* 0: disable beacon offload
+ * 1: enable beacon offload
+ * 2: update probe respond offload
+ */
+ u8 enable;
+ /* 0: legacy format (TXD + payload)
+ * 1: only cap field IE
+ */
+ u8 type;
+ __le16 pkt_len;
+ u8 pkt[512];
+ } __packed beacon_tlv;
+ } req = {
+ .hdr = {
+ .bss_idx = mvif->mt76.idx,
+ },
+ .beacon_tlv = {
+ .tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT),
+ .len = cpu_to_le16(sizeof(struct bcn_content_tlv)),
+ .enable = enable,
+ },
+ };
+ struct sk_buff *skb;
+
+ if (!enable)
+ goto out;
+
+ skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs);
+ if (!skb)
+ return -EINVAL;
+
+ if (skb->len > 512 - MT_TXD_SIZE) {
+ dev_err(dev->mt76.dev, "beacon size limit exceed\n");
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ mt7921_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb,
+ wcid, NULL, 0, true);
+ memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);
+ req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
+ req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
+
+ if (offs.cntdwn_counter_offs[0]) {
+ u16 csa_offs;
+
+ csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;
+ req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs);
+ }
+ dev_kfree_skb(skb);
+
+out:
+ return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),
+ &req, sizeof(req), true);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index 7690364bc079..5ca584bb2fc6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -155,7 +155,6 @@ struct mt7921_phy {
struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
- u32 rxfilter;
u64 omac_mask;
u16 noise;
@@ -212,6 +211,10 @@ struct mt7921_dev {
struct mt76_connac_pm pm;
struct mt76_connac_coredump coredump;
const struct mt7921_hif_ops *hif_ops;
+
+ struct work_struct ipv6_ns_work;
+ /* IPv6 addresses for WoWLAN */
+ struct sk_buff_head ipv6_ns_list;
};
enum {
@@ -450,6 +453,10 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev);
int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev);
void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data);
void mt7921_set_runtime_pm(struct mt7921_dev *dev);
+void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac,
+ struct ieee80211_vif *vif);
+void mt7921_set_ipv6_ns_work(struct work_struct *work);
+
int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
bool enable);
@@ -467,7 +474,11 @@ bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update);
int mt7921u_mcu_power_on(struct mt7921_dev *dev);
int mt7921u_wfsys_reset(struct mt7921_dev *dev);
-int mt7921u_dma_init(struct mt7921_dev *dev);
+int mt7921u_dma_init(struct mt7921_dev *dev, bool resume);
int mt7921u_init_reset(struct mt7921_dev *dev);
int mt7921u_mac_reset(struct mt7921_dev *dev);
+int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
+ struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ bool enable);
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 1a01d025bbe5..b5fb22b8e086 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -119,7 +119,6 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
mt7921_mcu_exit(dev);
tasklet_disable(&dev->irq_tasklet);
- mt76_free_device(&dev->mt76);
}
static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
@@ -302,8 +301,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
dev->bus_ops = dev->mt76.bus;
bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
GFP_KERNEL);
- if (!bus_ops)
- return -ENOMEM;
+ if (!bus_ops) {
+ ret = -ENOMEM;
+ goto err_free_dev;
+ }
bus_ops->rr = mt7921_rr;
bus_ops->wr = mt7921_wr;
@@ -312,7 +313,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
ret = __mt7921e_mcu_drv_pmctrl(dev);
if (ret)
- return ret;
+ goto err_free_dev;
mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) |
(mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
@@ -354,6 +355,7 @@ static void mt7921_pci_remove(struct pci_dev *pdev)
mt7921e_unregister_device(dev);
devm_free_irq(&pdev->dev, pdev->irq, dev);
+ mt76_free_device(&dev->mt76);
pci_free_irq_vectors(pdev);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
index 6712ff60c722..ea643260ceb6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
@@ -516,4 +516,9 @@
#define MT_TOP_MISC2_FW_PWR_ON BIT(0)
#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0)
+#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs))
+#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028)
+#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6)
+#define MT_WF_SW_SER_DONE_SUSPEND BIT(7)
+
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
index b7771e9f1fcd..dc38baef273a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
@@ -246,7 +246,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
if (ret)
goto error;
- ret = mt7921u_dma_init(dev);
+ ret = mt7921u_dma_init(dev, false);
if (ret)
return ret;
@@ -288,6 +288,61 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf)
mt76_free_device(&dev->mt76);
}
+#ifdef CONFIG_PM
+static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
+{
+ struct mt7921_dev *dev = usb_get_intfdata(intf);
+ int err;
+
+ err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
+ if (err)
+ return err;
+
+ mt76u_stop_rx(&dev->mt76);
+ mt76u_stop_tx(&dev->mt76);
+
+ set_bit(MT76_STATE_SUSPEND, &dev->mphy.state);
+
+ return 0;
+}
+
+static int mt7921u_resume(struct usb_interface *intf)
+{
+ struct mt7921_dev *dev = usb_get_intfdata(intf);
+ bool reinit = true;
+ int err, i;
+
+ for (i = 0; i < 10; i++) {
+ u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT);
+
+ if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) {
+ reinit = false;
+ break;
+ }
+ if (val & MT_WF_SW_SER_DONE_SUSPEND) {
+ mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0);
+ break;
+ }
+
+ msleep(20);
+ }
+
+ if (reinit || mt7921_dma_need_reinit(dev)) {
+ err = mt7921u_dma_init(dev, true);
+ if (err)
+ return err;
+ }
+
+ clear_bit(MT76_STATE_SUSPEND, &dev->mphy.state);
+
+ err = mt76u_resume_rx(&dev->mt76);
+ if (err < 0)
+ return err;
+
+ return mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
+}
+#endif /* CONFIG_PM */
+
MODULE_DEVICE_TABLE(usb, mt7921u_device_table);
MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
MODULE_FIRMWARE(MT7921_ROM_PATCH);
@@ -297,6 +352,11 @@ static struct usb_driver mt7921u_driver = {
.id_table = mt7921u_device_table,
.probe = mt7921u_probe,
.disconnect = mt7921u_disconnect,
+#ifdef CONFIG_PM
+ .suspend = mt7921u_suspend,
+ .resume = mt7921u_resume,
+ .reset_resume = mt7921u_resume,
+#endif /* CONFIG_PM */
.soft_unbind = 1,
.disable_hub_initiated_lpm = 1,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c
index 99bcbd858b65..cd2f09743d2f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c
@@ -121,7 +121,7 @@ static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset)
mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
}
-int mt7921u_dma_init(struct mt7921_dev *dev)
+int mt7921u_dma_init(struct mt7921_dev *dev, bool resume)
{
int err;
@@ -136,6 +136,9 @@ int mt7921u_dma_init(struct mt7921_dev *dev)
MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT);
mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT);
+ if (resume)
+ return 0;
+
err = mt7921u_dma_rx_evt_ep4(dev);
if (err)
return err;
@@ -221,7 +224,7 @@ int mt7921u_mac_reset(struct mt7921_dev *dev)
if (err)
goto out;
- err = mt7921u_dma_init(dev);
+ err = mt7921u_dma_init(dev, false);
if (err)
goto out;
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 6b8c9dc80542..1d08d99e298c 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -66,9 +66,8 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
wcid = rcu_dereference(dev->wcid[cb->wcid]);
if (wcid) {
status.sta = wcid_to_sta(wcid);
-
- if (status.sta)
- status.rate = &wcid->rate;
+ status.rates = NULL;
+ status.n_rates = 0;
}
hw = mt76_tx_status_get_hw(dev, skb);
@@ -120,7 +119,7 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
memset(cb, 0, sizeof(*cb));
- if (!wcid)
+ if (!wcid || !rcu_access_pointer(dev->wcid[wcid->idx]))
return MT_PACKET_ID_NO_ACK;
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
@@ -436,12 +435,11 @@ mt76_txq_stopped(struct mt76_queue *q)
static int
mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
- struct mt76_txq *mtxq)
+ struct mt76_txq *mtxq, struct mt76_wcid *wcid)
{
struct mt76_dev *dev = phy->dev;
struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
enum mt76_txq_id qid = mt76_txq_get_qid(txq);
- struct mt76_wcid *wcid = mtxq->wcid;
struct ieee80211_tx_info *info;
struct sk_buff *skb;
int n_frames = 1;
@@ -463,7 +461,9 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
ieee80211_get_tx_rates(txq->vif, txq->sta, skb,
info->control.rates, 1);
+ spin_lock(&q->lock);
idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop);
+ spin_unlock(&q->lock);
if (idx < 0)
return idx;
@@ -483,14 +483,18 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
ieee80211_get_tx_rates(txq->vif, txq->sta, skb,
info->control.rates, 1);
+ spin_lock(&q->lock);
idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop);
+ spin_unlock(&q->lock);
if (idx < 0)
break;
n_frames++;
} while (1);
+ spin_lock(&q->lock);
dev->queue_ops->kick(dev, q);
+ spin_unlock(&q->lock);
return n_frames;
}
@@ -521,12 +525,10 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
break;
mtxq = (struct mt76_txq *)txq->drv_priv;
- wcid = mtxq->wcid;
- if (wcid && test_bit(MT_WCID_FLAG_PS, &wcid->flags))
+ wcid = rcu_dereference(dev->wcid[mtxq->wcid]);
+ if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags))
continue;
- spin_lock_bh(&q->lock);
-
if (mtxq->send_bar && mtxq->aggr) {
struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
struct ieee80211_sta *sta = txq->sta;
@@ -535,15 +537,11 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
u8 tid = txq->tid;
mtxq->send_bar = false;
- spin_unlock_bh(&q->lock);
ieee80211_send_bar(vif, sta->addr, tid, agg_ssn);
- spin_lock_bh(&q->lock);
}
if (!mt76_txq_stopped(q))
- n_frames = mt76_txq_send_burst(phy, q, mtxq);
-
- spin_unlock_bh(&q->lock);
+ n_frames = mt76_txq_send_burst(phy, q, mtxq, wcid);
ieee80211_return_txq(phy->hw, txq, false);
@@ -563,6 +561,7 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)
if (qid >= 4)
return;
+ local_bh_disable();
rcu_read_lock();
do {
@@ -572,6 +571,7 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)
} while (len > 0);
rcu_read_unlock();
+ local_bh_enable();
}
EXPORT_SYMBOL_GPL(mt76_txq_schedule);
@@ -721,12 +721,17 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
spin_lock_bh(&dev->token_lock);
- token = idr_alloc(&dev->token, *ptxwi, 0, dev->drv->token_size,
- GFP_ATOMIC);
+ token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC);
if (token >= 0)
dev->token_count++;
- if (dev->token_count >= dev->drv->token_size - MT76_TOKEN_FREE_THR)
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ if (mtk_wed_device_active(&dev->mmio.wed) &&
+ token >= dev->mmio.wed.wlan.token_start)
+ dev->wed_token_count++;
+#endif
+
+ if (dev->token_count >= dev->token_size - MT76_TOKEN_FREE_THR)
__mt76_set_tx_blocked(dev, true);
spin_unlock_bh(&dev->token_lock);
@@ -743,10 +748,18 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
spin_lock_bh(&dev->token_lock);
txwi = idr_remove(&dev->token, token);
- if (txwi)
+ if (txwi) {
dev->token_count--;
- if (dev->token_count < dev->drv->token_size - MT76_TOKEN_FREE_THR &&
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ if (mtk_wed_device_active(&dev->mmio.wed) &&
+ token >= dev->mmio.wed.wlan.token_start &&
+ --dev->wed_token_count == 0)
+ wake_up(&dev->tx_wait);
+#endif
+ }
+
+ if (dev->token_count < dev->token_size - MT76_TOKEN_FREE_THR &&
dev->phy.q_tx[0]->blocked)
*wake = true;
diff --git a/drivers/net/wireless/microchip/wilc1000/hif.h b/drivers/net/wireless/microchip/wilc1000/hif.h
index cccd54ed0518..77616fc77575 100644
--- a/drivers/net/wireless/microchip/wilc1000/hif.h
+++ b/drivers/net/wireless/microchip/wilc1000/hif.h
@@ -123,7 +123,7 @@ struct wilc_remain_ch {
u32 duration;
void (*expired)(void *priv, u64 cookie);
void *arg;
- u32 cookie;
+ u64 cookie;
};
struct wilc;
diff --git a/drivers/net/wireless/microchip/wilc1000/mon.c b/drivers/net/wireless/microchip/wilc1000/mon.c
index 6bd63934c2d8..b5a1b65c087c 100644
--- a/drivers/net/wireless/microchip/wilc1000/mon.c
+++ b/drivers/net/wireless/microchip/wilc1000/mon.c
@@ -233,7 +233,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops;
wl->monitor_dev->needs_free_netdev = true;
- if (cfg80211_register_netdevice(wl->monitor_dev)) {
+ if (register_netdevice(wl->monitor_dev)) {
netdev_err(real_dev, "register_netdevice failed\n");
free_netdev(wl->monitor_dev);
return NULL;
@@ -251,7 +251,7 @@ void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked)
return;
if (rtnl_locked)
- cfg80211_unregister_netdevice(wl->monitor_dev);
+ unregister_netdevice(wl->monitor_dev);
else
unregister_netdev(wl->monitor_dev);
wl->monitor_dev = NULL;
diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c
index 643bddaae32a..3c292e3464c2 100644
--- a/drivers/net/wireless/microchip/wilc1000/netdev.c
+++ b/drivers/net/wireless/microchip/wilc1000/netdev.c
@@ -14,6 +14,7 @@
#include "wlan_cfg.h"
#define WILC_MULTICAST_TABLE_SIZE 8
+#define WILC_MAX_FW_VERSION_STR_SIZE 50
/* latest API version supported */
#define WILC1000_API_VER 1
@@ -522,7 +523,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) {
int size;
- char firmware_ver[20];
+ char firmware_ver[WILC_MAX_FW_VERSION_STR_SIZE];
size = wilc_wlan_cfg_get_val(wl, WID_FIRMWARE_VERSION,
firmware_ver,
diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c
index ec595dbd8959..7962c11cfe84 100644
--- a/drivers/net/wireless/microchip/wilc1000/sdio.c
+++ b/drivers/net/wireless/microchip/wilc1000/sdio.c
@@ -598,7 +598,7 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume)
cmd.read_write = 1;
cmd.function = 0;
cmd.raw = 1;
- cmd.address = SDIO_FBR_BASE(func->num);
+ cmd.address = SDIO_FBR_BASE(1);
cmd.data = SDIO_FBR_ENABLE_CSA;
ret = wilc_sdio_cmd52(wilc, &cmd);
if (ret) {
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
index fb5633a05fd5..48441f0389ca 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.c
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
@@ -875,14 +875,15 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
char *bssid;
u8 mgmt_ptk = 0;
+ if (vmm_table[i] == 0 || vmm_entries_ac[i] >= NQUEUES)
+ break;
+
tqe = wilc_wlan_txq_remove_from_head(wilc, vmm_entries_ac[i]);
- ac_pkt_num_to_chip[vmm_entries_ac[i]]++;
if (!tqe)
break;
+ ac_pkt_num_to_chip[vmm_entries_ac[i]]++;
vif = tqe->vif;
- if (vmm_table[i] == 0)
- break;
le32_to_cpus(&vmm_table[i]);
vmm_sz = FIELD_GET(WILC_VMM_BUFFER_SIZE, vmm_table[i]);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
index 840728ed57b2..8c23a77d1671 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
@@ -1146,8 +1146,8 @@ static int qtnf_pcie_pearl_probe(struct qtnf_bus *bus, unsigned int tx_bd_size,
}
tasklet_setup(&ps->base.reclaim_tq, qtnf_pearl_reclaim_tasklet_fn);
- netif_napi_add(&bus->mux_dev, &bus->mux_napi,
- qtnf_pcie_pearl_rx_poll, 10);
+ netif_napi_add_weight(&bus->mux_dev, &bus->mux_napi,
+ qtnf_pcie_pearl_rx_poll, 10);
ipc_int.fn = qtnf_pcie_pearl_ipc_gen_ep_int;
ipc_int.arg = ps;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
index 9534e1b33780..d83362578374 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
@@ -1159,8 +1159,8 @@ static int qtnf_pcie_topaz_probe(struct qtnf_bus *bus,
}
tasklet_setup(&ts->base.reclaim_tq, qtnf_reclaim_tasklet_fn);
- netif_napi_add(&bus->mux_dev, &bus->mux_napi,
- qtnf_topaz_rx_poll, 10);
+ netif_napi_add_weight(&bus->mux_dev, &bus->mux_napi,
+ qtnf_topaz_rx_poll, 10);
ipc_int.fn = qtnf_topaz_ipc_gen_ep_int;
ipc_int.arg = ts;
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index 86a236873254..a8eebafb9a7e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -1014,7 +1014,7 @@ int rtl_usb_probe(struct usb_interface *intf,
hw = ieee80211_alloc_hw(sizeof(struct rtl_priv) +
sizeof(struct rtl_usb_priv), &rtl_ops);
if (!hw) {
- WARN_ONCE(true, "rtl_usb: ieee80211 alloc failed\n");
+ pr_warn("rtl_usb: ieee80211 alloc failed\n");
return -ENOMEM;
}
rtlpriv = hw->priv;
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index e344e058f943..090610e48d08 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -1786,7 +1786,7 @@ void rtw_fw_adaptivity(struct rtw_dev *rtwdev)
SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_ADAPTIVITY);
SET_ADAPTIVITY_MODE(h2c_pkt, dm_info->edcca_mode);
- SET_ADAPTIVITY_OPTION(h2c_pkt, 2);
+ SET_ADAPTIVITY_OPTION(h2c_pkt, 1);
SET_ADAPTIVITY_IGI(h2c_pkt, dm_info->igi_history[0]);
SET_ADAPTIVITY_L2H(h2c_pkt, dm_info->l2h_th_ini);
SET_ADAPTIVITY_DENSITY(h2c_pkt, dm_info->scan_density);
diff --git a/drivers/net/wireless/realtek/rtw89/Kconfig b/drivers/net/wireless/realtek/rtw89/Kconfig
index dd02b6a6790e..93e09400aac4 100644
--- a/drivers/net/wireless/realtek/rtw89/Kconfig
+++ b/drivers/net/wireless/realtek/rtw89/Kconfig
@@ -19,8 +19,11 @@ config RTW89_PCI
config RTW89_8852A
tristate
+config RTW89_8852C
+ tristate
+
config RTW89_8852AE
- tristate "Realtek 8852AE PCI wireless network adapter"
+ tristate "Realtek 8852AE PCI wireless network (Wi-Fi 6) adapter"
depends on PCI
select RTW89_CORE
select RTW89_PCI
@@ -28,7 +31,18 @@ config RTW89_8852AE
help
Select this option will enable support for 8852AE chipset
- 802.11ax PCIe wireless network adapter
+ 802.11ax PCIe wireless network (Wi-Fi 6) adapter
+
+config RTW89_8852CE
+ tristate "Realtek 8852CE PCI wireless network (Wi-Fi 6E) adapter"
+ depends on PCI
+ select RTW89_CORE
+ select RTW89_PCI
+ select RTW89_8852C
+ help
+ Select this option will enable support for 8852CE chipset
+
+ 802.11ax PCIe wireless network (Wi-Fi 6E) adapter
config RTW89_DEBUG
bool
diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile
index 012ae60c0b81..3006482d25c7 100644
--- a/drivers/net/wireless/realtek/rtw89/Makefile
+++ b/drivers/net/wireless/realtek/rtw89/Makefile
@@ -23,6 +23,15 @@ rtw89_8852a-objs := rtw8852a.o \
obj-$(CONFIG_RTW89_8852AE) += rtw89_8852ae.o
rtw89_8852ae-objs := rtw8852ae.o
+obj-$(CONFIG_RTW89_8852C) += rtw89_8852c.o
+rtw89_8852c-objs := rtw8852c.o \
+ rtw8852c_table.o \
+ rtw8852c_rfk.o \
+ rtw8852c_rfk_table.o
+
+obj-$(CONFIG_RTW89_8852CE) += rtw89_8852ce.o
+rtw89_8852ce-objs := rtw8852ce.o
+
rtw89_core-$(CONFIG_RTW89_DEBUG) += debug.o
obj-$(CONFIG_RTW89_PCI) += rtw89_pci.o
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index e3317deafa1d..a6a90572e74b 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -1608,10 +1608,13 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
if (rtwdev->scanning &&
RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
- rx_status->freq =
- ieee80211_channel_to_frequency(hal->current_channel,
- hal->current_band_type);
- rx_status->band = rtwdev->hal.current_band_type;
+ u8 chan = hal->current_channel;
+ u8 band = hal->current_band_type;
+ enum nl80211_band nl_band;
+
+ nl_band = rtw89_hw_to_nl80211_band(band);
+ rx_status->freq = ieee80211_channel_to_frequency(chan, nl_band);
+ rx_status->band = nl_band;
}
if (desc_info->icv_err || desc_info->crc32_err)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 2921814842ff..e8a77225a90f 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -3481,6 +3481,20 @@ static inline u8 rtw89_hw_to_rate_info_bw(enum rtw89_bandwidth hw_bw)
}
static inline
+enum nl80211_band rtw89_hw_to_nl80211_band(enum rtw89_band hw_band)
+{
+ switch (hw_band) {
+ default:
+ case RTW89_BAND_2G:
+ return NL80211_BAND_2GHZ;
+ case RTW89_BAND_5G:
+ return NL80211_BAND_5GHZ;
+ case RTW89_BAND_6G:
+ return NL80211_BAND_6GHZ;
+ }
+}
+
+static inline
enum rtw89_bandwidth nl_to_rtw89_bandwidth(enum nl80211_chan_width width)
{
switch (width) {
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index f93f3fee1505..7820bc3ab3b4 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -635,6 +635,11 @@ static int rtw89_debug_priv_mac_reg_dump_get(struct seq_file *m, void *v)
start = 0x000;
end = 0x014;
break;
+ case RTW89_DBG_SEL_MAC_30:
+ seq_puts(m, "Debug selected MAC page 0x30\n");
+ start = 0x030;
+ end = 0x033;
+ break;
case RTW89_DBG_SEL_MAC_40:
seq_puts(m, "Debug selected MAC page 0x40\n");
start = 0x040;
diff --git a/drivers/net/wireless/realtek/rtw89/debug.h b/drivers/net/wireless/realtek/rtw89/debug.h
index 1745815f5e00..de72155ad1fe 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.h
+++ b/drivers/net/wireless/realtek/rtw89/debug.h
@@ -28,6 +28,7 @@ enum rtw89_debug_mask {
enum rtw89_debug_mac_reg_sel {
RTW89_DBG_SEL_MAC_00,
+ RTW89_DBG_SEL_MAC_30,
RTW89_DBG_SEL_MAC_40,
RTW89_DBG_SEL_MAC_80,
RTW89_DBG_SEL_MAC_C0,
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index e4be785709d1..4718aced1428 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -2068,7 +2068,7 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
struct rtw89_pktofld_info *info, *tmp;
u8 idx;
- for (idx = RTW89_BAND_2G; idx < NUM_NL80211_BANDS; idx++) {
+ for (idx = NL80211_BAND_2GHZ; idx < NUM_NL80211_BANDS; idx++) {
if (!(rtwdev->chip->support_bands & BIT(idx)))
continue;
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 05b94842fe66..3cf892912c1d 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -29,6 +29,7 @@ const u32 rtw89_mac_mem_base_addrs[RTW89_MAC_MEM_NUM] = {
[RTW89_MAC_MEM_TXDATA_FIFO_0] = TXDATA_FIFO_0_BASE_ADDR,
[RTW89_MAC_MEM_TXDATA_FIFO_1] = TXDATA_FIFO_1_BASE_ADDR,
[RTW89_MAC_MEM_CPU_LOCAL] = CPU_LOCAL_BASE_ADDR,
+ [RTW89_MAC_MEM_BSSID_CAM] = BSSID_CAM_BASE_ADDR,
};
static void rtw89_mac_mem_write(struct rtw89_dev *rtwdev, u32 offset,
@@ -1050,6 +1051,7 @@ static int rtw89_mac_check_cpwm_state(struct rtw89_dev *rtwdev,
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;
if (enter)
@@ -1059,7 +1061,7 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
rtw89_mac_send_rpwm(rtwdev, state, false);
ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret, !ret,
- 1000, 15000, false, rtwdev, state);
+ delay, 15000, false, rtwdev, state);
if (ret)
rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n",
enter ? "entering" : "leaving");
@@ -1889,11 +1891,12 @@ static int cca_ctrl_init(struct rtw89_dev *rtwdev, u8 mac_idx)
B_AX_CTN_CHK_BASIC_NAV | B_AX_CTN_CHK_BTCCA |
B_AX_CTN_CHK_EDCCA | B_AX_CTN_CHK_CCA_S80 |
B_AX_CTN_CHK_CCA_S40 | B_AX_CTN_CHK_CCA_S20 |
- B_AX_CTN_CHK_CCA_P20 | B_AX_SIFS_CHK_EDCCA);
+ B_AX_CTN_CHK_CCA_P20);
val &= ~(B_AX_TB_CHK_TX_NAV | B_AX_TB_CHK_CCA_S80 |
B_AX_TB_CHK_CCA_S40 | B_AX_TB_CHK_CCA_S20 |
B_AX_SIFS_CHK_CCA_S80 | B_AX_SIFS_CHK_CCA_S40 |
- B_AX_SIFS_CHK_CCA_S20 | B_AX_CTN_CHK_TXNAV);
+ B_AX_SIFS_CHK_CCA_S20 | B_AX_CTN_CHK_TXNAV |
+ B_AX_SIFS_CHK_EDCCA);
rtw89_write32(rtwdev, reg, val);
@@ -2004,6 +2007,7 @@ static int rmac_init(struct rtw89_dev *rtwdev, u8 mac_idx)
#define TRXCFG_RMAC_DATA_TO 15
#define RX_MAX_LEN_UNIT 512
#define PLD_RLS_MAX_PG 127
+#define RX_SPEC_MAX_LEN (11454 + RX_MAX_LEN_UNIT)
int ret;
u32 reg, rx_max_len, rx_qta;
u16 val;
@@ -2034,11 +2038,10 @@ static int rmac_init(struct rtw89_dev *rtwdev, u8 mac_idx)
rx_qta = rtwdev->mac.dle_info.c0_rx_qta;
else
rx_qta = rtwdev->mac.dle_info.c1_rx_qta;
- rx_qta = rx_qta > PLD_RLS_MAX_PG ? PLD_RLS_MAX_PG : rx_qta;
- rx_max_len = (rx_qta - 1) * rtwdev->mac.dle_info.ple_pg_size /
- RX_MAX_LEN_UNIT;
- rx_max_len = rx_max_len > B_AX_RX_MPDU_MAX_LEN_SIZE ?
- B_AX_RX_MPDU_MAX_LEN_SIZE : rx_max_len;
+ rx_qta = min_t(u32, rx_qta, PLD_RLS_MAX_PG);
+ rx_max_len = rx_qta * rtwdev->mac.dle_info.ple_pg_size;
+ rx_max_len = min_t(u32, rx_max_len, RX_SPEC_MAX_LEN);
+ rx_max_len /= RX_MAX_LEN_UNIT;
rtw89_write32_mask(rtwdev, reg, B_AX_RX_MPDU_MAX_LEN_MASK, rx_max_len);
if (rtwdev->chip->chip_id == RTL8852A &&
@@ -4239,6 +4242,10 @@ static int rtw89_mac_init_bfee(struct rtw89_dev *rtwdev, u8 mac_idx)
u32_encode_bits(CSI_INIT_RATE_VHT, B_AX_BFMEE_VHT_CSI_RATE_MASK) |
u32_encode_bits(CSI_INIT_RATE_HE, B_AX_BFMEE_HE_CSI_RATE_MASK));
+ reg = rtw89_mac_reg_by_idx(R_AX_CSIRPT_OPTION, mac_idx);
+ rtw89_write32_set(rtwdev, reg,
+ B_AX_CSIPRT_VHTSU_AID_EN | B_AX_CSIPRT_HESU_AID_EN);
+
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 9eb4afe348b3..9f511c8d8a37 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -268,6 +268,7 @@ enum rtw89_mac_mem_sel {
RTW89_MAC_MEM_TXDATA_FIFO_0,
RTW89_MAC_MEM_TXDATA_FIFO_1,
RTW89_MAC_MEM_CPU_LOCAL,
+ RTW89_MAC_MEM_BSSID_CAM,
/* keep last */
RTW89_MAC_MEM_NUM,
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 8da3e117ad38..f24e4a208376 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -630,7 +630,7 @@ static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta
rtwsta->use_cfg_mask = true;
rtwsta->mask = *br_data->mask;
- rtw89_phy_ra_updata_sta(br_data->rtwdev, sta);
+ rtw89_phy_ra_updata_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED);
}
static void rtw89_ra_mask_info_update(struct rtw89_dev *rtwdev,
@@ -759,6 +759,15 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw,
mutex_unlock(&rtwdev->mutex);
}
+static void rtw89_ops_sta_rc_update(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, u32 changed)
+{
+ struct rtw89_dev *rtwdev = hw->priv;
+
+ rtw89_phy_ra_updata_sta(rtwdev, sta, changed);
+}
+
const struct ieee80211_ops rtw89_ops = {
.tx = rtw89_ops_tx,
.wake_tx_queue = rtw89_ops_wake_tx_queue,
@@ -788,5 +797,6 @@ const struct ieee80211_ops rtw89_ops = {
.hw_scan = rtw89_ops_hw_scan,
.cancel_hw_scan = rtw89_ops_cancel_hw_scan,
.set_sar_specs = rtw89_ops_set_sar_specs,
+ .sta_rc_update = rtw89_ops_sta_rc_update,
};
EXPORT_SYMBOL(rtw89_ops);
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 2bdce7024f25..0ef7821b2e0f 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -682,9 +682,6 @@ EXPORT_SYMBOL(rtw89_pci_enable_intr_v1);
void rtw89_pci_disable_intr_v1(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci)
{
rtw89_write32(rtwdev, R_AX_PCIE_HIMR00_V1, 0);
- rtw89_write32(rtwdev, R_AX_HIMR0, 0);
- rtw89_write32(rtwdev, R_AX_HAXI_HIMR00, 0);
- rtw89_write32(rtwdev, R_AX_HIMR1, 0);
}
EXPORT_SYMBOL(rtw89_pci_disable_intr_v1);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 33494e8451cf..762cdba9d3cf 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -357,13 +357,19 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
ra->csi_mode = csi_mode;
}
-void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta)
+void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
+ u32 changed)
{
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rtw89_ra_info *ra = &rtwsta->ra;
rtw89_phy_ra_sta_update(rtwdev, sta, false);
- ra->upd_mask = 1;
+
+ if (changed & IEEE80211_RC_SUPP_RATES_CHANGED)
+ ra->upd_mask = 1;
+ if (changed & (IEEE80211_RC_BW_CHANGED | IEEE80211_RC_NSS_CHANGED))
+ ra->upd_bw_nss_mask = 1;
+
rtw89_debug(rtwdev, RTW89_DBG_RA,
"ra updat: macid = %d, bw = %d, nss = %d, gi = %d %d",
ra->macid,
@@ -423,27 +429,28 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
RTW89_HW_RATE_MCS16,
RTW89_HW_RATE_MCS24};
u8 band = rtwdev->hal.current_band_type;
+ enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
u8 tx_nss = rtwdev->hal.tx_nss;
u8 i;
for (i = 0; i < tx_nss; i++)
if (!__check_rate_pattern(&next_pattern, hw_rate_he[i],
RA_MASK_HE_RATES, RTW89_RA_MODE_HE,
- mask->control[band].he_mcs[i],
+ mask->control[nl_band].he_mcs[i],
0, true))
goto out;
for (i = 0; i < tx_nss; i++)
if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i],
RA_MASK_VHT_RATES, RTW89_RA_MODE_VHT,
- mask->control[band].vht_mcs[i],
+ mask->control[nl_band].vht_mcs[i],
0, true))
goto out;
for (i = 0; i < tx_nss; i++)
if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i],
RA_MASK_HT_RATES, RTW89_RA_MODE_HT,
- mask->control[band].ht_mcs[i],
+ mask->control[nl_band].ht_mcs[i],
0, true))
goto out;
@@ -451,18 +458,18 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
* require at least one basic rate for ieee80211_set_bitrate_mask,
* so the decision just depends on if all bitrates are set or not.
*/
- sband = rtwdev->hw->wiphy->bands[band];
+ sband = rtwdev->hw->wiphy->bands[nl_band];
if (band == RTW89_BAND_2G) {
if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_CCK1,
RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES,
RTW89_RA_MODE_CCK | RTW89_RA_MODE_OFDM,
- mask->control[band].legacy,
+ mask->control[nl_band].legacy,
BIT(sband->n_bitrates) - 1, false))
goto out;
} else {
if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_OFDM6,
RA_MASK_OFDM_RATES, RTW89_RA_MODE_OFDM,
- mask->control[band].legacy,
+ mask->control[nl_band].legacy,
BIT(sband->n_bitrates) - 1, false))
goto out;
}
@@ -487,7 +494,7 @@ static void rtw89_phy_ra_updata_sta_iter(void *data, struct ieee80211_sta *sta)
{
struct rtw89_dev *rtwdev = (struct rtw89_dev *)data;
- rtw89_phy_ra_updata_sta(rtwdev, sta);
+ rtw89_phy_ra_updata_sta(rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED);
}
void rtw89_phy_ra_update(struct rtw89_dev *rtwdev)
@@ -2456,6 +2463,11 @@ void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val,
struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
u8 macid = phy_ppdu->mac_id;
+ if (macid >= CFO_TRACK_MAX_USER) {
+ rtw89_warn(rtwdev, "mac_id %d is out of range\n", macid);
+ return;
+ }
+
cfo->cfo_tail[macid] += cfo_val;
cfo->cfo_cnt[macid]++;
cfo->packet_count++;
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 3ca5efa4c097..291660154d58 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -471,7 +471,8 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev,
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);
-void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta);
+void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
+ u32 changed);
void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 6f5d1012c90c..ebf28719d935 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -2605,7 +2605,6 @@
B_AX_TMAC_HWSIGB_GEN | \
B_AX_TMAC_RXTB | \
B_AX_TMAC_MIMO_CTRL | \
- B_AX_RMAC_CSI | \
B_AX_RMAC_FTM)
#define R_AX_WMAC_TX_TF_INFO_0 0xCCD0
@@ -2842,6 +2841,11 @@
#define R_AX_RX_SR_CTRL_C1 0xEE4A
#define B_AX_SR_EN BIT(0)
+#define R_AX_CSIRPT_OPTION 0xCE64
+#define R_AX_CSIRPT_OPTION_C1 0xEE64
+#define B_AX_CSIPRT_HESU_AID_EN BIT(25)
+#define B_AX_CSIPRT_VHTSU_AID_EN BIT(24)
+
#define R_AX_RX_STATE_MONITOR 0xCEF0
#define R_AX_RX_STATE_MONITOR_C1 0xEEF0
#define B_AX_RX_STATE_MONITOR_MASK GENMASK(31, 0)
@@ -3662,7 +3666,7 @@
#define R_DCFO 0x4264
#define B_DCFO GENMASK(1, 0)
#define R_SEG0CSI 0x42AC
-#define B_SEG0CSI_IDX GENMASK(10, 0)
+#define B_SEG0CSI_IDX GENMASK(11, 0)
#define R_SEG0CSI_EN 0x42C4
#define B_SEG0CSI_EN BIT(23)
#define R_BSS_CLR_MAP 0x43ac
@@ -3818,6 +3822,8 @@
#define B_CHBW_MOD_SBW GENMASK(13, 12)
#define B_CHBW_MOD_PRICH GENMASK(11, 8)
#define B_ANT_RX_SEG0 GENMASK(3, 0)
+#define R_PD_BOOST_EN 0x49E8
+#define B_PD_BOOST_EN BIT(7)
#define R_P1_BACKOFF_IBADC_V1 0x49F0
#define B_P1_BACKOFF_IBADC_V1 GENMASK(31, 26)
#define R_BK_FC0_INV_V1 0x4A1C
@@ -3836,6 +3842,12 @@
#define B_PATH1_BT_BACKOFF_V1 GENMASK(23, 0)
#define R_PATH0_FRC_FIR_TYPE_V1 0x4C00
#define B_PATH0_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0)
+#define R_PATH0_NOTCH 0x4C14
+#define B_PATH0_NOTCH_EN BIT(12)
+#define B_PATH0_NOTCH_VAL GENMASK(11, 0)
+#define R_PATH0_NOTCH2 0x4C20
+#define B_PATH0_NOTCH2_EN BIT(12)
+#define B_PATH0_NOTCH2_VAL GENMASK(11, 0)
#define R_PATH0_5MDET 0x4C4C
#define B_PATH0_5MDET_EN BIT(12)
#define B_PATH0_5MDET_SB2 BIT(8)
@@ -3843,6 +3855,12 @@
#define B_PATH0_5MDET_TH GENMASK(5, 0)
#define R_PATH1_FRC_FIR_TYPE_V1 0x4CC4
#define B_PATH1_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0)
+#define R_PATH1_NOTCH 0x4CD8
+#define B_PATH1_NOTCH_EN BIT(12)
+#define B_PATH1_NOTCH_VAL GENMASK(11, 0)
+#define R_PATH1_NOTCH2 0x4CE4
+#define B_PATH1_NOTCH2_EN BIT(12)
+#define B_PATH1_NOTCH2_VAL GENMASK(11, 0)
#define R_PATH1_5MDET 0x4D10
#define B_PATH1_5MDET_EN BIT(12)
#define B_PATH1_5MDET_SB2 BIT(8)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 4fb3de71d032..64840c8d9efe 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -1381,19 +1381,72 @@ static void rtw8852c_set_nbi_tone_idx(struct rtw89_dev *rtwdev,
}
}
+static void rtw8852c_spur_notch(struct rtw89_dev *rtwdev, u32 val,
+ enum rtw89_phy_idx phy_idx)
+{
+ u32 notch;
+ u32 notch2;
+
+ if (phy_idx == RTW89_PHY_0) {
+ notch = R_PATH0_NOTCH;
+ notch2 = R_PATH0_NOTCH2;
+ } else {
+ notch = R_PATH1_NOTCH;
+ notch2 = R_PATH1_NOTCH2;
+ }
+
+ rtw89_phy_write32_mask(rtwdev, notch,
+ B_PATH0_NOTCH_VAL | B_PATH0_NOTCH_EN, val);
+ rtw89_phy_write32_set(rtwdev, notch, B_PATH0_NOTCH_EN);
+ rtw89_phy_write32_mask(rtwdev, notch2,
+ B_PATH0_NOTCH2_VAL | B_PATH0_NOTCH2_EN, val);
+ rtw89_phy_write32_set(rtwdev, notch2, B_PATH0_NOTCH2_EN);
+}
+
static void rtw8852c_spur_elimination(struct rtw89_dev *rtwdev,
struct rtw89_channel_params *param,
+ u8 pri_ch_idx,
enum rtw89_phy_idx phy_idx)
{
rtw8852c_set_csi_tone_idx(rtwdev, param, phy_idx);
if (phy_idx == RTW89_PHY_0) {
- rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_A);
- if (!rtwdev->dbcc_en)
- rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_B);
+ if (param->bandwidth == 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 &&
+ (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);
+ if (!rtwdev->dbcc_en)
+ rtw8852c_set_nbi_tone_idx(rtwdev, param,
+ RF_PATH_B);
+ }
} else {
- rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_B);
+ if (param->bandwidth == 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 &&
+ (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);
+ }
}
+
+ if (pri_ch_idx == RTW89_SC_20_UP3X || pri_ch_idx == RTW89_SC_20_LOW3X)
+ rtw89_phy_write32_idx(rtwdev, R_PD_BOOST_EN, B_PD_BOOST_EN, 0, phy_idx);
+ else
+ rtw89_phy_write32_idx(rtwdev, R_PD_BOOST_EN, B_PD_BOOST_EN, 1, phy_idx);
}
static void rtw8852c_5m_mask(struct rtw89_dev *rtwdev,
@@ -1664,7 +1717,7 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
B_PD_ARBITER_OFF, 0x1, phy_idx);
}
- rtw8852c_spur_elimination(rtwdev, param, 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);
@@ -1786,6 +1839,7 @@ static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev)
{
enum rtw89_phy_idx phy_idx = RTW89_PHY_0;
+ rtw8852c_mcc_get_ch_info(rtwdev, phy_idx);
rtw8852c_rx_dck(rtwdev, phy_idx, false);
rtw8852c_iqk(rtwdev, phy_idx);
rtw8852c_tssi(rtwdev, phy_idx);
@@ -2306,19 +2360,19 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path,
rtw89_write32(rtwdev, reg, 0);
}
- if (tx_path == RF_PATH_A) {
+ if (tx_path == RF_A) {
path_com[0].data = AX_PATH_COM0_PATHA;
path_com[1].data = AX_PATH_COM1_PATHA;
path_com[2].data = AX_PATH_COM2_PATHA;
path_com[7].data = AX_PATH_COM7_PATHA;
path_com[8].data = AX_PATH_COM8_PATHA;
- } else if (tx_path == RF_PATH_B) {
+ } else if (tx_path == RF_B) {
path_com[0].data = AX_PATH_COM0_PATHB;
path_com[1].data = AX_PATH_COM1_PATHB;
path_com[2].data = AX_PATH_COM2_PATHB;
path_com[7].data = AX_PATH_COM7_PATHB;
path_com[8].data = AX_PATH_COM8_PATHB;
- } else if (tx_path == RF_PATH_AB) {
+ } else if (tx_path == RF_AB) {
path_com[0].data = AX_PATH_COM0_PATHAB;
path_com[1].data = AX_PATH_COM1_PATHAB;
path_com[2].data = AX_PATH_COM2_PATHAB;
@@ -2337,9 +2391,73 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path,
}
}
+static void rtw8852c_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en)
+{
+ if (bt_en) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_FRC_FIR_TYPE_V1,
+ B_PATH0_FRC_FIR_TYPE_MSK_V1, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_FRC_FIR_TYPE_V1,
+ B_PATH1_FRC_FIR_TYPE_MSK_V1, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_RXBB_V1,
+ B_PATH0_RXBB_MSK_V1, 0xf);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_RXBB_V1,
+ B_PATH1_RXBB_MSK_V1, 0xf);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x80);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_G_LNA6_OP1DB_V1,
+ B_PATH1_G_LNA6_OP1DB_V1, 0x80);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x80);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA1_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA1_LNA6_OP1DB_V1, 0x80);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH1_G_TIA0_LNA6_OP1DB_V1, 0x80);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_G_TIA1_LNA6_OP1DB_V1,
+ B_PATH1_G_TIA1_LNA6_OP1DB_V1, 0x80);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_BACKOFF_V1,
+ B_PATH0_BT_BACKOFF_V1, 0x780D1E);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_BT_BACKOFF_V1,
+ B_PATH1_BT_BACKOFF_V1, 0x780D1E);
+ rtw89_phy_write32_mask(rtwdev, R_P0_BACKOFF_IBADC_V1,
+ B_P0_BACKOFF_IBADC_V1, 0x34);
+ rtw89_phy_write32_mask(rtwdev, R_P1_BACKOFF_IBADC_V1,
+ B_P1_BACKOFF_IBADC_V1, 0x34);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_FRC_FIR_TYPE_V1,
+ B_PATH0_FRC_FIR_TYPE_MSK_V1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_FRC_FIR_TYPE_V1,
+ B_PATH1_FRC_FIR_TYPE_MSK_V1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_RXBB_V1,
+ B_PATH0_RXBB_MSK_V1, 0x60);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_RXBB_V1,
+ B_PATH1_RXBB_MSK_V1, 0x60);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x1a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_G_LNA6_OP1DB_V1,
+ B_PATH1_G_LNA6_OP1DB_V1, 0x1a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA1_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA1_LNA6_OP1DB_V1, 0x2a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH1_G_TIA0_LNA6_OP1DB_V1, 0x2a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_G_TIA1_LNA6_OP1DB_V1,
+ B_PATH1_G_TIA1_LNA6_OP1DB_V1, 0x2a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_BACKOFF_V1,
+ B_PATH0_BT_BACKOFF_V1, 0x79E99E);
+ rtw89_phy_write32_mask(rtwdev, R_PATH1_BT_BACKOFF_V1,
+ B_PATH1_BT_BACKOFF_V1, 0x79E99E);
+ rtw89_phy_write32_mask(rtwdev, R_P0_BACKOFF_IBADC_V1,
+ B_P0_BACKOFF_IBADC_V1, 0x26);
+ rtw89_phy_write32_mask(rtwdev, R_P1_BACKOFF_IBADC_V1,
+ B_P1_BACKOFF_IBADC_V1, 0x26);
+ }
+}
+
static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
+ u8 ntx_path = hal->antenna_tx ? hal->antenna_tx : RF_AB;
rtw8852c_bb_cfg_rx_path(rtwdev, RF_PATH_AB);
@@ -2355,7 +2473,7 @@ static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 1);
}
- rtw8852c_ctrl_tx_path_tmac(rtwdev, RF_PATH_AB, RTW89_MAC_0);
+ rtw8852c_ctrl_tx_path_tmac(rtwdev, ntx_path, RTW89_MAC_0);
}
static u8 rtw8852c_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path)
@@ -2552,16 +2670,14 @@ rtw8852c_btc_set_wl_txpwr_ctrl(struct rtw89_dev *rtwdev, u32 txpwr_val)
#define __write_ctrl(_reg, _msk, _val, _en, _cond) \
do { \
- const typeof(_msk) __msk = _msk; \
- const typeof(_en) __en = _en; \
- u32 _wrt = FIELD_PREP(__msk, _val); \
- BUILD_BUG_ON((__msk & __en) != 0); \
+ u32 _wrt = FIELD_PREP(_msk, _val); \
+ BUILD_BUG_ON((_msk & _en) != 0); \
if (_cond) \
- _wrt |= __en; \
+ _wrt |= _en; \
else \
- _wrt &= ~__en; \
+ _wrt &= ~_en; \
rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, _reg, \
- __msk | __en, _wrt); \
+ _msk | _en, _wrt); \
} while (0)
switch (arg.ctrl_all_time) {
@@ -2598,6 +2714,48 @@ s8 rtw8852c_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val)
return clamp_t(s8, val, -100, 0) + 100;
}
+static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_ul[] = {
+ {255, 0, 0, 7}, /* 0 -> original */
+ {255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */
+ {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* the below id is for non-shared-antenna free-run */
+ {6, 1, 0, 7},
+ {13, 1, 0, 7},
+ {13, 1, 0, 7}
+};
+
+static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_dl[] = {
+ {255, 0, 0, 7}, /* 0 -> original */
+ {255, 2, 0, 7}, /* 1 -> reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* the below id is for non-shared-antenna free-run */
+ {255, 1, 0, 7},
+ {255, 1, 0, 7},
+ {255, 1, 0, 7}
+};
+
+static const u8 rtw89_btc_8852c_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {60, 50, 40, 30};
+static const u8 rtw89_btc_8852c_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {40, 36, 31, 28};
+
+static const struct rtw89_btc_fbtc_mreg rtw89_btc_8852c_mon_reg[] = {
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda00),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda04),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda24),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda30),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda34),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda38),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda44),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda48),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda4c),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd200),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd220),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980),
+};
+
static
void rtw8852c_btc_bt_aci_imp(struct rtw89_dev *rtwdev)
{
@@ -2731,10 +2889,13 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.disable_bb_rf = rtw8852c_mac_disable_bb_rf,
.bb_reset = rtw8852c_bb_reset,
.bb_sethw = rtw8852c_bb_sethw,
+ .read_rf = rtw89_phy_read_rf_v1,
+ .write_rf = rtw89_phy_write_rf_v1,
.set_channel = rtw8852c_set_channel,
.set_channel_help = rtw8852c_set_channel_help,
.read_efuse = rtw8852c_read_efuse,
.read_phycap = rtw8852c_read_phycap,
+ .fem_setup = NULL,
.rfk_init = rtw8852c_rfk_init,
.rfk_channel = rtw8852c_rfk_channel,
.rfk_band_changed = rtw8852c_rfk_band_changed,
@@ -2745,11 +2906,11 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.set_txpwr_ctrl = rtw8852c_set_txpwr_ctrl,
.init_txpwr_unit = rtw8852c_init_txpwr_unit,
.get_thermal = rtw8852c_get_thermal,
+ .ctrl_btg = rtw8852c_ctrl_btg,
.query_ppdu = rtw8852c_query_ppdu,
- .read_rf = rtw89_phy_read_rf_v1,
- .write_rf = rtw89_phy_write_rf_v1,
- .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset,
+ .bb_ctrl_btc_preagc = rtw8852c_bb_ctrl_btc_preagc,
.cfg_txrx_path = rtw8852c_bb_cfg_txrx_path,
+ .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset,
.pwr_on_func = rtw8852c_pwr_on_func,
.pwr_off_func = rtw8852c_pwr_off_func,
.fill_txdesc = rtw89_core_fill_txdesc_v1,
@@ -2774,6 +2935,10 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.chip_id = RTL8852C,
.ops = &rtw8852c_chip_ops,
.fw_name = "rtw89/rtw8852c_fw.bin",
+ .fifo_size = 458752,
+ .max_amsdu_limit = 8000,
+ .dis_2g_40m_ul_ofdma = false,
+ .rsvd_ple_ofst = 0x6f800,
.hfc_param_ini = rtw8852c_hfc_param_ini_pcie,
.dle_mem = rtw8852c_dle_mem_pcie,
.rf_base_addr = {0xe000, 0xf000},
@@ -2795,7 +2960,17 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.txpwr_factor_mac = 1,
.dig_table = NULL,
.tssi_dbw_table = &rtw89_8852c_tssi_dbw_table,
+ .support_bands = BIT(NL80211_BAND_2GHZ) |
+ BIT(NL80211_BAND_5GHZ) |
+ BIT(NL80211_BAND_6GHZ),
+ .support_bw160 = true,
.hw_sec_hdr = true,
+ .rf_path_num = 2,
+ .tx_nss = 2,
+ .rx_nss = 2,
+ .acam_num = 128,
+ .bcam_num = 20,
+ .scam_num = 128,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 2048,
@@ -2804,6 +2979,22 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.dav_log_efuse_size = 16,
.phycap_addr = 0x590,
.phycap_size = 0x60,
+ .para_ver = 0x05050764,
+ .wlcx_desired = 0x05050000,
+ .btcx_desired = 0x5,
+ .scbd = 0x1,
+ .mailbox = 0x1,
+ .afh_guard_ch = 6,
+ .wl_rssi_thres = rtw89_btc_8852c_wl_rssi_thres,
+ .bt_rssi_thres = rtw89_btc_8852c_bt_rssi_thres,
+ .rssi_tol = 2,
+ .mon_reg_num = ARRAY_SIZE(rtw89_btc_8852c_mon_reg),
+ .mon_reg = rtw89_btc_8852c_mon_reg,
+ .rf_para_ulink_num = ARRAY_SIZE(rtw89_btc_8852c_rf_ul),
+ .rf_para_ulink = rtw89_btc_8852c_rf_ul,
+ .rf_para_dlink_num = ARRAY_SIZE(rtw89_btc_8852c_rf_dl),
+ .rf_para_dlink = rtw89_btc_8852c_rf_dl,
+ .ps_mode_supported = 0,
.low_power_hci_modes = BIT(RTW89_PS_MODE_CLK_GATED) |
BIT(RTW89_PS_MODE_PWR_GATED),
.h2c_cctl_func_id = H2C_FUNC_MAC_CCTLINFO_UD_V1,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
index ffc71ad24927..dfb9caba9bc4 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
@@ -3809,6 +3809,24 @@ void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev,
param->bandwidth);
}
+void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_mcc_info *mcc_info = &rtwdev->mcc;
+ u8 idx = mcc_info->table_idx;
+ int i;
+
+ for (i = 0; i < RTW89_IQK_CHS_NR; i++) {
+ if (mcc_info->ch[idx] == 0)
+ break;
+ if (++idx >= RTW89_IQK_CHS_NR)
+ idx = 0;
+ }
+
+ mcc_info->table_idx = idx;
+ mcc_info->ch[idx] = rtwdev->hal.current_channel;
+ mcc_info->band[idx] = rtwdev->hal.current_band_type;
+}
+
void rtw8852c_rck(struct rtw89_dev *rtwdev)
{
u8 path;
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h
index e42fb1a4965e..c32756f0c01a 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h
@@ -7,6 +7,7 @@
#include "core.h"
+void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
void rtw8852c_rck(struct rtw89_dev *rtwdev);
void rtw8852c_dack(struct rtw89_dev *rtwdev);
void rtw8852c_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
index 477c46041c94..feaa83b16171 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
@@ -13678,27 +13678,27 @@ static const struct rtw89_txpwr_byrate_cfg rtw89_8852c_txpwr_byrate[] = {
{ 0, 1, 3, 0, 4, 0x50505050, },
{ 0, 0, 4, 1, 4, 0x00000000, },
{ 0, 0, 4, 0, 1, 0x00000000, },
- { 1, 0, 1, 0, 4, 0x5054585c, },
- { 1, 0, 1, 4, 4, 0x4044484c, },
- { 1, 0, 2, 0, 4, 0x4c505458, },
+ { 1, 0, 1, 0, 4, 0x48484848, },
+ { 1, 0, 1, 4, 4, 0x40444848, },
+ { 1, 0, 2, 0, 4, 0x48484848, },
{ 1, 0, 2, 4, 4, 0x3c404448, },
{ 1, 0, 2, 8, 4, 0x2c303438, },
- { 1, 0, 3, 0, 4, 0x3c40484c, },
- { 1, 1, 2, 0, 4, 0x4c505458, },
+ { 1, 0, 3, 0, 4, 0x48484848, },
+ { 1, 1, 2, 0, 4, 0x48484848, },
{ 1, 1, 2, 4, 4, 0x3c404448, },
{ 1, 1, 2, 8, 4, 0x2c303438, },
- { 1, 1, 3, 0, 4, 0x3c40484c, },
+ { 1, 1, 3, 0, 4, 0x48484848, },
{ 1, 0, 4, 0, 4, 0x00000000, },
- { 2, 0, 1, 0, 4, 0x5054585c, },
- { 2, 0, 1, 4, 4, 0x4044484c, },
- { 2, 0, 2, 0, 4, 0x4c505458, },
- { 2, 0, 2, 4, 4, 0x3c404448, },
- { 2, 0, 2, 8, 4, 0x2c303438, },
- { 2, 0, 3, 0, 4, 0x3c40484c, },
- { 2, 1, 2, 0, 4, 0x4c505458, },
- { 2, 1, 2, 4, 4, 0x3c404448, },
- { 2, 1, 2, 8, 4, 0x2c303438, },
- { 2, 1, 3, 0, 4, 0x3c40484c, },
+ { 2, 0, 1, 0, 4, 0x40404040, },
+ { 2, 0, 1, 4, 4, 0x383c4040, },
+ { 2, 0, 2, 0, 4, 0x40404040, },
+ { 2, 0, 2, 4, 4, 0x34383c40, },
+ { 2, 0, 2, 8, 4, 0x24282c30, },
+ { 2, 0, 3, 0, 4, 0x40404040, },
+ { 2, 1, 2, 0, 4, 0x40404040, },
+ { 2, 1, 2, 4, 4, 0x34383c40, },
+ { 2, 1, 2, 8, 4, 0x24282c30, },
+ { 2, 1, 3, 0, 4, 0x40404040, },
{ 2, 0, 4, 0, 4, 0x00000000, },
};
@@ -13857,8 +13857,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[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] = 58,
- [0][0][0][0][RTW89_WW][13] = 74,
+ [0][0][0][0][RTW89_WW][12] = 48,
+ [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,
@@ -13870,34 +13870,34 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[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] = 48,
- [0][1][0][0][RTW89_WW][12] = 44,
- [0][1][0][0][RTW89_WW][13] = 62,
+ [0][1][0][0][RTW89_WW][11] = 46,
+ [0][1][0][0][RTW89_WW][12] = 34,
+ [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] = 52,
- [1][0][0][0][RTW89_WW][3] = 52,
- [1][0][0][0][RTW89_WW][4] = 52,
- [1][0][0][0][RTW89_WW][5] = 60,
- [1][0][0][0][RTW89_WW][6] = 52,
- [1][0][0][0][RTW89_WW][7] = 52,
- [1][0][0][0][RTW89_WW][8] = 52,
- [1][0][0][0][RTW89_WW][9] = 44,
- [1][0][0][0][RTW89_WW][10] = 32,
+ [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][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][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] = 48,
- [1][1][0][0][RTW89_WW][3] = 48,
- [1][1][0][0][RTW89_WW][4] = 48,
+ [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] = 36,
- [1][1][0][0][RTW89_WW][7] = 36,
- [1][1][0][0][RTW89_WW][8] = 36,
- [1][1][0][0][RTW89_WW][9] = 32,
- [1][1][0][0][RTW89_WW][10] = 32,
+ [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][11] = 0,
[1][1][0][0][RTW89_WW][12] = 0,
[1][1][0][0][RTW89_WW][13] = 0,
@@ -13912,8 +13912,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[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] = 56,
- [0][0][1][0][RTW89_WW][12] = 52,
+ [0][0][1][0][RTW89_WW][11] = 46,
+ [0][0][1][0][RTW89_WW][12] = 42,
[0][0][1][0][RTW89_WW][13] = 0,
[0][1][1][0][RTW89_WW][0] = 48,
[0][1][1][0][RTW89_WW][1] = 48,
@@ -13926,8 +13926,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[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] = 48,
- [0][1][1][0][RTW89_WW][12] = 44,
+ [0][1][1][0][RTW89_WW][11] = 38,
+ [0][1][1][0][RTW89_WW][12] = 34,
[0][1][1][0][RTW89_WW][13] = 0,
[0][0][2][0][RTW89_WW][0] = 60,
[0][0][2][0][RTW89_WW][1] = 60,
@@ -13940,8 +13940,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[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] = 56,
- [0][0][2][0][RTW89_WW][12] = 52,
+ [0][0][2][0][RTW89_WW][11] = 46,
+ [0][0][2][0][RTW89_WW][12] = 42,
[0][0][2][0][RTW89_WW][13] = 0,
[0][1][2][0][RTW89_WW][0] = 48,
[0][1][2][0][RTW89_WW][1] = 48,
@@ -13954,8 +13954,8 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[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] = 48,
- [0][1][2][0][RTW89_WW][12] = 44,
+ [0][1][2][0][RTW89_WW][11] = 38,
+ [0][1][2][0][RTW89_WW][12] = 34,
[0][1][2][0][RTW89_WW][13] = 0,
[0][1][2][1][RTW89_WW][0] = 36,
[0][1][2][1][RTW89_WW][1] = 36,
@@ -13969,7 +13969,7 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[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] = 36,
+ [0][1][2][1][RTW89_WW][12] = 34,
[0][1][2][1][RTW89_WW][13] = 0,
[1][0][2][0][RTW89_WW][0] = 0,
[1][0][2][0][RTW89_WW][1] = 0,
@@ -13981,21 +13981,21 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[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] = 60,
+ [1][0][2][0][RTW89_WW][10] = 58,
[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] = 48,
- [1][1][2][0][RTW89_WW][3] = 48,
+ [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] = 48,
- [1][1][2][0][RTW89_WW][8] = 48,
- [1][1][2][0][RTW89_WW][9] = 44,
- [1][1][2][0][RTW89_WW][10] = 40,
+ [1][1][2][0][RTW89_WW][7] = 46,
+ [1][1][2][0][RTW89_WW][8] = 46,
+ [1][1][2][0][RTW89_WW][9] = 34,
+ [1][1][2][0][RTW89_WW][10] = 30,
[1][1][2][0][RTW89_WW][11] = 0,
[1][1][2][0][RTW89_WW][12] = 0,
[1][1][2][0][RTW89_WW][13] = 0,
@@ -14008,149 +14008,149 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[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][9] = 36,
- [1][1][2][1][RTW89_WW][10] = 36,
+ [1][1][2][1][RTW89_WW][9] = 34,
+ [1][1][2][1][RTW89_WW][10] = 30,
[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] = 80,
+ [0][0][0][0][RTW89_FCC][0] = 70,
[0][0][0][0][RTW89_ETSI][0] = 60,
- [0][0][0][0][RTW89_MKK][0] = 72,
- [0][0][0][0][RTW89_IC][0] = 80,
+ [0][0][0][0][RTW89_MKK][0] = 68,
+ [0][0][0][0][RTW89_IC][0] = 74,
[0][0][0][0][RTW89_ACMA][0] = 60,
- [0][0][0][0][RTW89_FCC][1] = 80,
+ [0][0][0][0][RTW89_FCC][1] = 70,
[0][0][0][0][RTW89_ETSI][1] = 60,
- [0][0][0][0][RTW89_MKK][1] = 72,
- [0][0][0][0][RTW89_IC][1] = 80,
+ [0][0][0][0][RTW89_MKK][1] = 68,
+ [0][0][0][0][RTW89_IC][1] = 74,
[0][0][0][0][RTW89_ACMA][1] = 60,
- [0][0][0][0][RTW89_FCC][2] = 80,
+ [0][0][0][0][RTW89_FCC][2] = 70,
[0][0][0][0][RTW89_ETSI][2] = 60,
- [0][0][0][0][RTW89_MKK][2] = 72,
- [0][0][0][0][RTW89_IC][2] = 80,
+ [0][0][0][0][RTW89_MKK][2] = 68,
+ [0][0][0][0][RTW89_IC][2] = 74,
[0][0][0][0][RTW89_ACMA][2] = 60,
- [0][0][0][0][RTW89_FCC][3] = 80,
+ [0][0][0][0][RTW89_FCC][3] = 70,
[0][0][0][0][RTW89_ETSI][3] = 60,
- [0][0][0][0][RTW89_MKK][3] = 72,
- [0][0][0][0][RTW89_IC][3] = 80,
+ [0][0][0][0][RTW89_MKK][3] = 68,
+ [0][0][0][0][RTW89_IC][3] = 74,
[0][0][0][0][RTW89_ACMA][3] = 60,
- [0][0][0][0][RTW89_FCC][4] = 80,
+ [0][0][0][0][RTW89_FCC][4] = 70,
[0][0][0][0][RTW89_ETSI][4] = 60,
- [0][0][0][0][RTW89_MKK][4] = 72,
- [0][0][0][0][RTW89_IC][4] = 80,
+ [0][0][0][0][RTW89_MKK][4] = 68,
+ [0][0][0][0][RTW89_IC][4] = 74,
[0][0][0][0][RTW89_ACMA][4] = 60,
- [0][0][0][0][RTW89_FCC][5] = 80,
+ [0][0][0][0][RTW89_FCC][5] = 70,
[0][0][0][0][RTW89_ETSI][5] = 60,
- [0][0][0][0][RTW89_MKK][5] = 72,
- [0][0][0][0][RTW89_IC][5] = 80,
+ [0][0][0][0][RTW89_MKK][5] = 68,
+ [0][0][0][0][RTW89_IC][5] = 74,
[0][0][0][0][RTW89_ACMA][5] = 60,
- [0][0][0][0][RTW89_FCC][6] = 80,
+ [0][0][0][0][RTW89_FCC][6] = 70,
[0][0][0][0][RTW89_ETSI][6] = 60,
- [0][0][0][0][RTW89_MKK][6] = 72,
- [0][0][0][0][RTW89_IC][6] = 80,
+ [0][0][0][0][RTW89_MKK][6] = 68,
+ [0][0][0][0][RTW89_IC][6] = 74,
[0][0][0][0][RTW89_ACMA][6] = 60,
- [0][0][0][0][RTW89_FCC][7] = 80,
+ [0][0][0][0][RTW89_FCC][7] = 70,
[0][0][0][0][RTW89_ETSI][7] = 60,
- [0][0][0][0][RTW89_MKK][7] = 72,
- [0][0][0][0][RTW89_IC][7] = 80,
+ [0][0][0][0][RTW89_MKK][7] = 68,
+ [0][0][0][0][RTW89_IC][7] = 74,
[0][0][0][0][RTW89_ACMA][7] = 60,
- [0][0][0][0][RTW89_FCC][8] = 80,
+ [0][0][0][0][RTW89_FCC][8] = 70,
[0][0][0][0][RTW89_ETSI][8] = 60,
- [0][0][0][0][RTW89_MKK][8] = 72,
- [0][0][0][0][RTW89_IC][8] = 80,
+ [0][0][0][0][RTW89_MKK][8] = 68,
+ [0][0][0][0][RTW89_IC][8] = 74,
[0][0][0][0][RTW89_ACMA][8] = 60,
- [0][0][0][0][RTW89_FCC][9] = 80,
+ [0][0][0][0][RTW89_FCC][9] = 70,
[0][0][0][0][RTW89_ETSI][9] = 60,
- [0][0][0][0][RTW89_MKK][9] = 72,
- [0][0][0][0][RTW89_IC][9] = 80,
+ [0][0][0][0][RTW89_MKK][9] = 68,
+ [0][0][0][0][RTW89_IC][9] = 74,
[0][0][0][0][RTW89_ACMA][9] = 60,
- [0][0][0][0][RTW89_FCC][10] = 80,
+ [0][0][0][0][RTW89_FCC][10] = 70,
[0][0][0][0][RTW89_ETSI][10] = 60,
- [0][0][0][0][RTW89_MKK][10] = 72,
- [0][0][0][0][RTW89_IC][10] = 80,
+ [0][0][0][0][RTW89_MKK][10] = 68,
+ [0][0][0][0][RTW89_IC][10] = 74,
[0][0][0][0][RTW89_ACMA][10] = 60,
- [0][0][0][0][RTW89_FCC][11] = 72,
+ [0][0][0][0][RTW89_FCC][11] = 62,
[0][0][0][0][RTW89_ETSI][11] = 60,
- [0][0][0][0][RTW89_MKK][11] = 72,
+ [0][0][0][0][RTW89_MKK][11] = 68,
[0][0][0][0][RTW89_IC][11] = 72,
[0][0][0][0][RTW89_ACMA][11] = 60,
- [0][0][0][0][RTW89_FCC][12] = 58,
+ [0][0][0][0][RTW89_FCC][12] = 48,
[0][0][0][0][RTW89_ETSI][12] = 60,
- [0][0][0][0][RTW89_MKK][12] = 72,
+ [0][0][0][0][RTW89_MKK][12] = 68,
[0][0][0][0][RTW89_IC][12] = 58,
[0][0][0][0][RTW89_ACMA][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] = 74,
+ [0][0][0][0][RTW89_MKK][13] = 72,
[0][0][0][0][RTW89_IC][13] = 127,
[0][0][0][0][RTW89_ACMA][13] = 127,
- [0][1][0][0][RTW89_FCC][0] = 76,
+ [0][1][0][0][RTW89_FCC][0] = 66,
[0][1][0][0][RTW89_ETSI][0] = 48,
- [0][1][0][0][RTW89_MKK][0] = 60,
- [0][1][0][0][RTW89_IC][0] = 76,
+ [0][1][0][0][RTW89_MKK][0] = 58,
+ [0][1][0][0][RTW89_IC][0] = 74,
[0][1][0][0][RTW89_ACMA][0] = 48,
- [0][1][0][0][RTW89_FCC][1] = 76,
+ [0][1][0][0][RTW89_FCC][1] = 66,
[0][1][0][0][RTW89_ETSI][1] = 48,
- [0][1][0][0][RTW89_MKK][1] = 60,
- [0][1][0][0][RTW89_IC][1] = 76,
+ [0][1][0][0][RTW89_MKK][1] = 58,
+ [0][1][0][0][RTW89_IC][1] = 74,
[0][1][0][0][RTW89_ACMA][1] = 48,
- [0][1][0][0][RTW89_FCC][2] = 76,
+ [0][1][0][0][RTW89_FCC][2] = 66,
[0][1][0][0][RTW89_ETSI][2] = 48,
- [0][1][0][0][RTW89_MKK][2] = 60,
- [0][1][0][0][RTW89_IC][2] = 76,
+ [0][1][0][0][RTW89_MKK][2] = 58,
+ [0][1][0][0][RTW89_IC][2] = 74,
[0][1][0][0][RTW89_ACMA][2] = 48,
- [0][1][0][0][RTW89_FCC][3] = 76,
+ [0][1][0][0][RTW89_FCC][3] = 66,
[0][1][0][0][RTW89_ETSI][3] = 48,
- [0][1][0][0][RTW89_MKK][3] = 60,
- [0][1][0][0][RTW89_IC][3] = 76,
+ [0][1][0][0][RTW89_MKK][3] = 58,
+ [0][1][0][0][RTW89_IC][3] = 74,
[0][1][0][0][RTW89_ACMA][3] = 48,
- [0][1][0][0][RTW89_FCC][4] = 76,
+ [0][1][0][0][RTW89_FCC][4] = 66,
[0][1][0][0][RTW89_ETSI][4] = 48,
- [0][1][0][0][RTW89_MKK][4] = 60,
- [0][1][0][0][RTW89_IC][4] = 76,
+ [0][1][0][0][RTW89_MKK][4] = 58,
+ [0][1][0][0][RTW89_IC][4] = 74,
[0][1][0][0][RTW89_ACMA][4] = 48,
- [0][1][0][0][RTW89_FCC][5] = 76,
+ [0][1][0][0][RTW89_FCC][5] = 66,
[0][1][0][0][RTW89_ETSI][5] = 48,
- [0][1][0][0][RTW89_MKK][5] = 60,
- [0][1][0][0][RTW89_IC][5] = 76,
+ [0][1][0][0][RTW89_MKK][5] = 58,
+ [0][1][0][0][RTW89_IC][5] = 74,
[0][1][0][0][RTW89_ACMA][5] = 48,
- [0][1][0][0][RTW89_FCC][6] = 76,
+ [0][1][0][0][RTW89_FCC][6] = 66,
[0][1][0][0][RTW89_ETSI][6] = 48,
- [0][1][0][0][RTW89_MKK][6] = 60,
- [0][1][0][0][RTW89_IC][6] = 76,
+ [0][1][0][0][RTW89_MKK][6] = 58,
+ [0][1][0][0][RTW89_IC][6] = 74,
[0][1][0][0][RTW89_ACMA][6] = 48,
- [0][1][0][0][RTW89_FCC][7] = 76,
+ [0][1][0][0][RTW89_FCC][7] = 66,
[0][1][0][0][RTW89_ETSI][7] = 48,
- [0][1][0][0][RTW89_MKK][7] = 60,
- [0][1][0][0][RTW89_IC][7] = 76,
+ [0][1][0][0][RTW89_MKK][7] = 58,
+ [0][1][0][0][RTW89_IC][7] = 74,
[0][1][0][0][RTW89_ACMA][7] = 48,
- [0][1][0][0][RTW89_FCC][8] = 76,
+ [0][1][0][0][RTW89_FCC][8] = 66,
[0][1][0][0][RTW89_ETSI][8] = 48,
- [0][1][0][0][RTW89_MKK][8] = 60,
- [0][1][0][0][RTW89_IC][8] = 76,
+ [0][1][0][0][RTW89_MKK][8] = 58,
+ [0][1][0][0][RTW89_IC][8] = 74,
[0][1][0][0][RTW89_ACMA][8] = 48,
- [0][1][0][0][RTW89_FCC][9] = 76,
+ [0][1][0][0][RTW89_FCC][9] = 66,
[0][1][0][0][RTW89_ETSI][9] = 48,
- [0][1][0][0][RTW89_MKK][9] = 60,
- [0][1][0][0][RTW89_IC][9] = 76,
+ [0][1][0][0][RTW89_MKK][9] = 58,
+ [0][1][0][0][RTW89_IC][9] = 74,
[0][1][0][0][RTW89_ACMA][9] = 48,
- [0][1][0][0][RTW89_FCC][10] = 76,
+ [0][1][0][0][RTW89_FCC][10] = 66,
[0][1][0][0][RTW89_ETSI][10] = 48,
- [0][1][0][0][RTW89_MKK][10] = 60,
- [0][1][0][0][RTW89_IC][10] = 76,
+ [0][1][0][0][RTW89_MKK][10] = 58,
+ [0][1][0][0][RTW89_IC][10] = 74,
[0][1][0][0][RTW89_ACMA][10] = 48,
- [0][1][0][0][RTW89_FCC][11] = 56,
+ [0][1][0][0][RTW89_FCC][11] = 46,
[0][1][0][0][RTW89_ETSI][11] = 48,
- [0][1][0][0][RTW89_MKK][11] = 60,
+ [0][1][0][0][RTW89_MKK][11] = 58,
[0][1][0][0][RTW89_IC][11] = 56,
[0][1][0][0][RTW89_ACMA][11] = 48,
- [0][1][0][0][RTW89_FCC][12] = 44,
+ [0][1][0][0][RTW89_FCC][12] = 34,
[0][1][0][0][RTW89_ETSI][12] = 48,
- [0][1][0][0][RTW89_MKK][12] = 60,
+ [0][1][0][0][RTW89_MKK][12] = 58,
[0][1][0][0][RTW89_IC][12] = 44,
[0][1][0][0][RTW89_ACMA][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] = 62,
+ [0][1][0][0][RTW89_MKK][13] = 60,
[0][1][0][0][RTW89_IC][13] = 127,
[0][1][0][0][RTW89_ACMA][13] = 127,
[1][0][0][0][RTW89_FCC][0] = 127,
@@ -14163,49 +14163,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_MKK][1] = 127,
[1][0][0][0][RTW89_IC][1] = 127,
[1][0][0][0][RTW89_ACMA][1] = 127,
- [1][0][0][0][RTW89_FCC][2] = 52,
+ [1][0][0][0][RTW89_FCC][2] = 42,
[1][0][0][0][RTW89_ETSI][2] = 60,
- [1][0][0][0][RTW89_MKK][2] = 72,
+ [1][0][0][0][RTW89_MKK][2] = 66,
[1][0][0][0][RTW89_IC][2] = 52,
[1][0][0][0][RTW89_ACMA][2] = 60,
- [1][0][0][0][RTW89_FCC][3] = 52,
+ [1][0][0][0][RTW89_FCC][3] = 42,
[1][0][0][0][RTW89_ETSI][3] = 60,
- [1][0][0][0][RTW89_MKK][3] = 72,
+ [1][0][0][0][RTW89_MKK][3] = 66,
[1][0][0][0][RTW89_IC][3] = 52,
[1][0][0][0][RTW89_ACMA][3] = 60,
- [1][0][0][0][RTW89_FCC][4] = 52,
+ [1][0][0][0][RTW89_FCC][4] = 42,
[1][0][0][0][RTW89_ETSI][4] = 60,
- [1][0][0][0][RTW89_MKK][4] = 72,
+ [1][0][0][0][RTW89_MKK][4] = 66,
[1][0][0][0][RTW89_IC][4] = 52,
[1][0][0][0][RTW89_ACMA][4] = 60,
- [1][0][0][0][RTW89_FCC][5] = 68,
+ [1][0][0][0][RTW89_FCC][5] = 58,
[1][0][0][0][RTW89_ETSI][5] = 60,
- [1][0][0][0][RTW89_MKK][5] = 72,
+ [1][0][0][0][RTW89_MKK][5] = 66,
[1][0][0][0][RTW89_IC][5] = 68,
[1][0][0][0][RTW89_ACMA][5] = 60,
- [1][0][0][0][RTW89_FCC][6] = 52,
+ [1][0][0][0][RTW89_FCC][6] = 42,
[1][0][0][0][RTW89_ETSI][6] = 60,
- [1][0][0][0][RTW89_MKK][6] = 72,
+ [1][0][0][0][RTW89_MKK][6] = 66,
[1][0][0][0][RTW89_IC][6] = 52,
[1][0][0][0][RTW89_ACMA][6] = 60,
- [1][0][0][0][RTW89_FCC][7] = 52,
+ [1][0][0][0][RTW89_FCC][7] = 42,
[1][0][0][0][RTW89_ETSI][7] = 60,
- [1][0][0][0][RTW89_MKK][7] = 72,
+ [1][0][0][0][RTW89_MKK][7] = 66,
[1][0][0][0][RTW89_IC][7] = 52,
[1][0][0][0][RTW89_ACMA][7] = 60,
- [1][0][0][0][RTW89_FCC][8] = 52,
+ [1][0][0][0][RTW89_FCC][8] = 42,
[1][0][0][0][RTW89_ETSI][8] = 60,
- [1][0][0][0][RTW89_MKK][8] = 72,
+ [1][0][0][0][RTW89_MKK][8] = 66,
[1][0][0][0][RTW89_IC][8] = 52,
[1][0][0][0][RTW89_ACMA][8] = 60,
- [1][0][0][0][RTW89_FCC][9] = 44,
+ [1][0][0][0][RTW89_FCC][9] = 34,
[1][0][0][0][RTW89_ETSI][9] = 60,
- [1][0][0][0][RTW89_MKK][9] = 72,
+ [1][0][0][0][RTW89_MKK][9] = 66,
[1][0][0][0][RTW89_IC][9] = 44,
[1][0][0][0][RTW89_ACMA][9] = 60,
- [1][0][0][0][RTW89_FCC][10] = 32,
+ [1][0][0][0][RTW89_FCC][10] = 22,
[1][0][0][0][RTW89_ETSI][10] = 60,
- [1][0][0][0][RTW89_MKK][10] = 70,
+ [1][0][0][0][RTW89_MKK][10] = 66,
[1][0][0][0][RTW89_IC][10] = 32,
[1][0][0][0][RTW89_ACMA][10] = 60,
[1][0][0][0][RTW89_FCC][11] = 127,
@@ -14233,49 +14233,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_MKK][1] = 127,
[1][1][0][0][RTW89_IC][1] = 127,
[1][1][0][0][RTW89_ACMA][1] = 127,
- [1][1][0][0][RTW89_FCC][2] = 48,
+ [1][1][0][0][RTW89_FCC][2] = 38,
[1][1][0][0][RTW89_ETSI][2] = 48,
- [1][1][0][0][RTW89_MKK][2] = 60,
+ [1][1][0][0][RTW89_MKK][2] = 58,
[1][1][0][0][RTW89_IC][2] = 48,
[1][1][0][0][RTW89_ACMA][2] = 48,
- [1][1][0][0][RTW89_FCC][3] = 48,
+ [1][1][0][0][RTW89_FCC][3] = 38,
[1][1][0][0][RTW89_ETSI][3] = 48,
- [1][1][0][0][RTW89_MKK][3] = 60,
+ [1][1][0][0][RTW89_MKK][3] = 58,
[1][1][0][0][RTW89_IC][3] = 48,
[1][1][0][0][RTW89_ACMA][3] = 48,
- [1][1][0][0][RTW89_FCC][4] = 48,
+ [1][1][0][0][RTW89_FCC][4] = 38,
[1][1][0][0][RTW89_ETSI][4] = 48,
- [1][1][0][0][RTW89_MKK][4] = 60,
+ [1][1][0][0][RTW89_MKK][4] = 58,
[1][1][0][0][RTW89_IC][4] = 48,
[1][1][0][0][RTW89_ACMA][4] = 48,
- [1][1][0][0][RTW89_FCC][5] = 64,
+ [1][1][0][0][RTW89_FCC][5] = 54,
[1][1][0][0][RTW89_ETSI][5] = 48,
- [1][1][0][0][RTW89_MKK][5] = 60,
+ [1][1][0][0][RTW89_MKK][5] = 58,
[1][1][0][0][RTW89_IC][5] = 64,
[1][1][0][0][RTW89_ACMA][5] = 48,
- [1][1][0][0][RTW89_FCC][6] = 36,
+ [1][1][0][0][RTW89_FCC][6] = 26,
[1][1][0][0][RTW89_ETSI][6] = 48,
- [1][1][0][0][RTW89_MKK][6] = 60,
+ [1][1][0][0][RTW89_MKK][6] = 58,
[1][1][0][0][RTW89_IC][6] = 36,
[1][1][0][0][RTW89_ACMA][6] = 48,
- [1][1][0][0][RTW89_FCC][7] = 36,
+ [1][1][0][0][RTW89_FCC][7] = 26,
[1][1][0][0][RTW89_ETSI][7] = 48,
- [1][1][0][0][RTW89_MKK][7] = 60,
+ [1][1][0][0][RTW89_MKK][7] = 58,
[1][1][0][0][RTW89_IC][7] = 36,
[1][1][0][0][RTW89_ACMA][7] = 48,
- [1][1][0][0][RTW89_FCC][8] = 36,
+ [1][1][0][0][RTW89_FCC][8] = 26,
[1][1][0][0][RTW89_ETSI][8] = 48,
- [1][1][0][0][RTW89_MKK][8] = 60,
+ [1][1][0][0][RTW89_MKK][8] = 58,
[1][1][0][0][RTW89_IC][8] = 36,
[1][1][0][0][RTW89_ACMA][8] = 48,
- [1][1][0][0][RTW89_FCC][9] = 32,
+ [1][1][0][0][RTW89_FCC][9] = 22,
[1][1][0][0][RTW89_ETSI][9] = 48,
- [1][1][0][0][RTW89_MKK][9] = 60,
+ [1][1][0][0][RTW89_MKK][9] = 58,
[1][1][0][0][RTW89_IC][9] = 32,
[1][1][0][0][RTW89_ACMA][9] = 48,
- [1][1][0][0][RTW89_FCC][10] = 32,
+ [1][1][0][0][RTW89_FCC][10] = 22,
[1][1][0][0][RTW89_ETSI][10] = 48,
- [1][1][0][0][RTW89_MKK][10] = 58,
+ [1][1][0][0][RTW89_MKK][10] = 56,
[1][1][0][0][RTW89_IC][10] = 32,
[1][1][0][0][RTW89_ACMA][10] = 48,
[1][1][0][0][RTW89_FCC][11] = 127,
@@ -14293,69 +14293,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_MKK][13] = 127,
[1][1][0][0][RTW89_IC][13] = 127,
[1][1][0][0][RTW89_ACMA][13] = 127,
- [0][0][1][0][RTW89_FCC][0] = 78,
+ [0][0][1][0][RTW89_FCC][0] = 68,
[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_ACMA][0] = 60,
- [0][0][1][0][RTW89_FCC][1] = 78,
+ [0][0][1][0][RTW89_FCC][1] = 68,
[0][0][1][0][RTW89_ETSI][1] = 60,
- [0][0][1][0][RTW89_MKK][1] = 76,
+ [0][0][1][0][RTW89_MKK][1] = 78,
[0][0][1][0][RTW89_IC][1] = 78,
[0][0][1][0][RTW89_ACMA][1] = 60,
- [0][0][1][0][RTW89_FCC][2] = 80,
+ [0][0][1][0][RTW89_FCC][2] = 70,
[0][0][1][0][RTW89_ETSI][2] = 60,
- [0][0][1][0][RTW89_MKK][2] = 76,
- [0][0][1][0][RTW89_IC][2] = 80,
+ [0][0][1][0][RTW89_MKK][2] = 78,
+ [0][0][1][0][RTW89_IC][2] = 78,
[0][0][1][0][RTW89_ACMA][2] = 60,
- [0][0][1][0][RTW89_FCC][3] = 80,
+ [0][0][1][0][RTW89_FCC][3] = 70,
[0][0][1][0][RTW89_ETSI][3] = 60,
- [0][0][1][0][RTW89_MKK][3] = 76,
- [0][0][1][0][RTW89_IC][3] = 80,
+ [0][0][1][0][RTW89_MKK][3] = 78,
+ [0][0][1][0][RTW89_IC][3] = 78,
[0][0][1][0][RTW89_ACMA][3] = 60,
- [0][0][1][0][RTW89_FCC][4] = 80,
+ [0][0][1][0][RTW89_FCC][4] = 70,
[0][0][1][0][RTW89_ETSI][4] = 60,
- [0][0][1][0][RTW89_MKK][4] = 76,
- [0][0][1][0][RTW89_IC][4] = 80,
+ [0][0][1][0][RTW89_MKK][4] = 78,
+ [0][0][1][0][RTW89_IC][4] = 78,
[0][0][1][0][RTW89_ACMA][4] = 60,
- [0][0][1][0][RTW89_FCC][5] = 80,
+ [0][0][1][0][RTW89_FCC][5] = 70,
[0][0][1][0][RTW89_ETSI][5] = 60,
- [0][0][1][0][RTW89_MKK][5] = 76,
- [0][0][1][0][RTW89_IC][5] = 80,
+ [0][0][1][0][RTW89_MKK][5] = 78,
+ [0][0][1][0][RTW89_IC][5] = 78,
[0][0][1][0][RTW89_ACMA][5] = 60,
- [0][0][1][0][RTW89_FCC][6] = 80,
+ [0][0][1][0][RTW89_FCC][6] = 70,
[0][0][1][0][RTW89_ETSI][6] = 60,
[0][0][1][0][RTW89_MKK][6] = 76,
- [0][0][1][0][RTW89_IC][6] = 80,
+ [0][0][1][0][RTW89_IC][6] = 78,
[0][0][1][0][RTW89_ACMA][6] = 60,
- [0][0][1][0][RTW89_FCC][7] = 80,
+ [0][0][1][0][RTW89_FCC][7] = 70,
[0][0][1][0][RTW89_ETSI][7] = 60,
- [0][0][1][0][RTW89_MKK][7] = 76,
- [0][0][1][0][RTW89_IC][7] = 80,
+ [0][0][1][0][RTW89_MKK][7] = 78,
+ [0][0][1][0][RTW89_IC][7] = 78,
[0][0][1][0][RTW89_ACMA][7] = 60,
- [0][0][1][0][RTW89_FCC][8] = 80,
+ [0][0][1][0][RTW89_FCC][8] = 70,
[0][0][1][0][RTW89_ETSI][8] = 60,
- [0][0][1][0][RTW89_MKK][8] = 76,
- [0][0][1][0][RTW89_IC][8] = 80,
+ [0][0][1][0][RTW89_MKK][8] = 78,
+ [0][0][1][0][RTW89_IC][8] = 78,
[0][0][1][0][RTW89_ACMA][8] = 60,
- [0][0][1][0][RTW89_FCC][9] = 76,
+ [0][0][1][0][RTW89_FCC][9] = 66,
[0][0][1][0][RTW89_ETSI][9] = 60,
- [0][0][1][0][RTW89_MKK][9] = 76,
+ [0][0][1][0][RTW89_MKK][9] = 78,
[0][0][1][0][RTW89_IC][9] = 76,
[0][0][1][0][RTW89_ACMA][9] = 60,
- [0][0][1][0][RTW89_FCC][10] = 76,
+ [0][0][1][0][RTW89_FCC][10] = 66,
[0][0][1][0][RTW89_ETSI][10] = 60,
- [0][0][1][0][RTW89_MKK][10] = 76,
+ [0][0][1][0][RTW89_MKK][10] = 78,
[0][0][1][0][RTW89_IC][10] = 76,
[0][0][1][0][RTW89_ACMA][10] = 60,
- [0][0][1][0][RTW89_FCC][11] = 56,
+ [0][0][1][0][RTW89_FCC][11] = 46,
[0][0][1][0][RTW89_ETSI][11] = 60,
- [0][0][1][0][RTW89_MKK][11] = 76,
+ [0][0][1][0][RTW89_MKK][11] = 78,
[0][0][1][0][RTW89_IC][11] = 56,
[0][0][1][0][RTW89_ACMA][11] = 60,
- [0][0][1][0][RTW89_FCC][12] = 52,
+ [0][0][1][0][RTW89_FCC][12] = 42,
[0][0][1][0][RTW89_ETSI][12] = 60,
- [0][0][1][0][RTW89_MKK][12] = 76,
+ [0][0][1][0][RTW89_MKK][12] = 78,
[0][0][1][0][RTW89_IC][12] = 52,
[0][0][1][0][RTW89_ACMA][12] = 60,
[0][0][1][0][RTW89_FCC][13] = 127,
@@ -14363,69 +14363,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_MKK][13] = 127,
[0][0][1][0][RTW89_IC][13] = 127,
[0][0][1][0][RTW89_ACMA][13] = 127,
- [0][1][1][0][RTW89_FCC][0] = 64,
+ [0][1][1][0][RTW89_FCC][0] = 54,
[0][1][1][0][RTW89_ETSI][0] = 48,
- [0][1][1][0][RTW89_MKK][0] = 68,
+ [0][1][1][0][RTW89_MKK][0] = 66,
[0][1][1][0][RTW89_IC][0] = 64,
[0][1][1][0][RTW89_ACMA][0] = 48,
- [0][1][1][0][RTW89_FCC][1] = 64,
+ [0][1][1][0][RTW89_FCC][1] = 54,
[0][1][1][0][RTW89_ETSI][1] = 48,
- [0][1][1][0][RTW89_MKK][1] = 68,
+ [0][1][1][0][RTW89_MKK][1] = 66,
[0][1][1][0][RTW89_IC][1] = 64,
[0][1][1][0][RTW89_ACMA][1] = 48,
- [0][1][1][0][RTW89_FCC][2] = 68,
+ [0][1][1][0][RTW89_FCC][2] = 58,
[0][1][1][0][RTW89_ETSI][2] = 48,
- [0][1][1][0][RTW89_MKK][2] = 68,
+ [0][1][1][0][RTW89_MKK][2] = 66,
[0][1][1][0][RTW89_IC][2] = 68,
[0][1][1][0][RTW89_ACMA][2] = 48,
- [0][1][1][0][RTW89_FCC][3] = 72,
+ [0][1][1][0][RTW89_FCC][3] = 62,
[0][1][1][0][RTW89_ETSI][3] = 48,
- [0][1][1][0][RTW89_MKK][3] = 68,
+ [0][1][1][0][RTW89_MKK][3] = 66,
[0][1][1][0][RTW89_IC][3] = 72,
[0][1][1][0][RTW89_ACMA][3] = 48,
- [0][1][1][0][RTW89_FCC][4] = 80,
+ [0][1][1][0][RTW89_FCC][4] = 70,
[0][1][1][0][RTW89_ETSI][4] = 48,
- [0][1][1][0][RTW89_MKK][4] = 68,
- [0][1][1][0][RTW89_IC][4] = 80,
+ [0][1][1][0][RTW89_MKK][4] = 66,
+ [0][1][1][0][RTW89_IC][4] = 78,
[0][1][1][0][RTW89_ACMA][4] = 48,
- [0][1][1][0][RTW89_FCC][5] = 80,
+ [0][1][1][0][RTW89_FCC][5] = 70,
[0][1][1][0][RTW89_ETSI][5] = 48,
- [0][1][1][0][RTW89_MKK][5] = 68,
- [0][1][1][0][RTW89_IC][5] = 80,
+ [0][1][1][0][RTW89_MKK][5] = 66,
+ [0][1][1][0][RTW89_IC][5] = 78,
[0][1][1][0][RTW89_ACMA][5] = 48,
- [0][1][1][0][RTW89_FCC][6] = 80,
+ [0][1][1][0][RTW89_FCC][6] = 70,
[0][1][1][0][RTW89_ETSI][6] = 48,
- [0][1][1][0][RTW89_MKK][6] = 68,
- [0][1][1][0][RTW89_IC][6] = 80,
+ [0][1][1][0][RTW89_MKK][6] = 66,
+ [0][1][1][0][RTW89_IC][6] = 78,
[0][1][1][0][RTW89_ACMA][6] = 48,
- [0][1][1][0][RTW89_FCC][7] = 72,
+ [0][1][1][0][RTW89_FCC][7] = 62,
[0][1][1][0][RTW89_ETSI][7] = 48,
- [0][1][1][0][RTW89_MKK][7] = 68,
+ [0][1][1][0][RTW89_MKK][7] = 66,
[0][1][1][0][RTW89_IC][7] = 72,
[0][1][1][0][RTW89_ACMA][7] = 48,
- [0][1][1][0][RTW89_FCC][8] = 68,
+ [0][1][1][0][RTW89_FCC][8] = 58,
[0][1][1][0][RTW89_ETSI][8] = 48,
- [0][1][1][0][RTW89_MKK][8] = 68,
+ [0][1][1][0][RTW89_MKK][8] = 66,
[0][1][1][0][RTW89_IC][8] = 68,
[0][1][1][0][RTW89_ACMA][8] = 48,
- [0][1][1][0][RTW89_FCC][9] = 64,
+ [0][1][1][0][RTW89_FCC][9] = 54,
[0][1][1][0][RTW89_ETSI][9] = 48,
- [0][1][1][0][RTW89_MKK][9] = 68,
+ [0][1][1][0][RTW89_MKK][9] = 66,
[0][1][1][0][RTW89_IC][9] = 64,
[0][1][1][0][RTW89_ACMA][9] = 48,
- [0][1][1][0][RTW89_FCC][10] = 64,
+ [0][1][1][0][RTW89_FCC][10] = 54,
[0][1][1][0][RTW89_ETSI][10] = 48,
- [0][1][1][0][RTW89_MKK][10] = 68,
+ [0][1][1][0][RTW89_MKK][10] = 66,
[0][1][1][0][RTW89_IC][10] = 64,
[0][1][1][0][RTW89_ACMA][10] = 48,
- [0][1][1][0][RTW89_FCC][11] = 48,
+ [0][1][1][0][RTW89_FCC][11] = 38,
[0][1][1][0][RTW89_ETSI][11] = 48,
- [0][1][1][0][RTW89_MKK][11] = 68,
+ [0][1][1][0][RTW89_MKK][11] = 66,
[0][1][1][0][RTW89_IC][11] = 48,
[0][1][1][0][RTW89_ACMA][11] = 48,
- [0][1][1][0][RTW89_FCC][12] = 44,
+ [0][1][1][0][RTW89_FCC][12] = 34,
[0][1][1][0][RTW89_ETSI][12] = 48,
- [0][1][1][0][RTW89_MKK][12] = 68,
+ [0][1][1][0][RTW89_MKK][12] = 66,
[0][1][1][0][RTW89_IC][12] = 44,
[0][1][1][0][RTW89_ACMA][12] = 48,
[0][1][1][0][RTW89_FCC][13] = 127,
@@ -14433,69 +14433,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_MKK][13] = 127,
[0][1][1][0][RTW89_IC][13] = 127,
[0][1][1][0][RTW89_ACMA][13] = 127,
- [0][0][2][0][RTW89_FCC][0] = 78,
+ [0][0][2][0][RTW89_FCC][0] = 68,
[0][0][2][0][RTW89_ETSI][0] = 60,
- [0][0][2][0][RTW89_MKK][0] = 76,
+ [0][0][2][0][RTW89_MKK][0] = 78,
[0][0][2][0][RTW89_IC][0] = 78,
[0][0][2][0][RTW89_ACMA][0] = 60,
- [0][0][2][0][RTW89_FCC][1] = 78,
+ [0][0][2][0][RTW89_FCC][1] = 68,
[0][0][2][0][RTW89_ETSI][1] = 60,
- [0][0][2][0][RTW89_MKK][1] = 76,
+ [0][0][2][0][RTW89_MKK][1] = 78,
[0][0][2][0][RTW89_IC][1] = 78,
[0][0][2][0][RTW89_ACMA][1] = 60,
- [0][0][2][0][RTW89_FCC][2] = 80,
+ [0][0][2][0][RTW89_FCC][2] = 70,
[0][0][2][0][RTW89_ETSI][2] = 60,
- [0][0][2][0][RTW89_MKK][2] = 76,
- [0][0][2][0][RTW89_IC][2] = 80,
+ [0][0][2][0][RTW89_MKK][2] = 78,
+ [0][0][2][0][RTW89_IC][2] = 78,
[0][0][2][0][RTW89_ACMA][2] = 60,
- [0][0][2][0][RTW89_FCC][3] = 80,
+ [0][0][2][0][RTW89_FCC][3] = 70,
[0][0][2][0][RTW89_ETSI][3] = 60,
- [0][0][2][0][RTW89_MKK][3] = 76,
- [0][0][2][0][RTW89_IC][3] = 80,
+ [0][0][2][0][RTW89_MKK][3] = 78,
+ [0][0][2][0][RTW89_IC][3] = 78,
[0][0][2][0][RTW89_ACMA][3] = 60,
- [0][0][2][0][RTW89_FCC][4] = 80,
+ [0][0][2][0][RTW89_FCC][4] = 70,
[0][0][2][0][RTW89_ETSI][4] = 60,
- [0][0][2][0][RTW89_MKK][4] = 76,
- [0][0][2][0][RTW89_IC][4] = 80,
+ [0][0][2][0][RTW89_MKK][4] = 78,
+ [0][0][2][0][RTW89_IC][4] = 78,
[0][0][2][0][RTW89_ACMA][4] = 60,
- [0][0][2][0][RTW89_FCC][5] = 80,
+ [0][0][2][0][RTW89_FCC][5] = 70,
[0][0][2][0][RTW89_ETSI][5] = 60,
- [0][0][2][0][RTW89_MKK][5] = 76,
- [0][0][2][0][RTW89_IC][5] = 80,
+ [0][0][2][0][RTW89_MKK][5] = 78,
+ [0][0][2][0][RTW89_IC][5] = 78,
[0][0][2][0][RTW89_ACMA][5] = 60,
- [0][0][2][0][RTW89_FCC][6] = 80,
+ [0][0][2][0][RTW89_FCC][6] = 70,
[0][0][2][0][RTW89_ETSI][6] = 60,
- [0][0][2][0][RTW89_MKK][6] = 76,
- [0][0][2][0][RTW89_IC][6] = 80,
+ [0][0][2][0][RTW89_MKK][6] = 78,
+ [0][0][2][0][RTW89_IC][6] = 78,
[0][0][2][0][RTW89_ACMA][6] = 60,
- [0][0][2][0][RTW89_FCC][7] = 80,
+ [0][0][2][0][RTW89_FCC][7] = 70,
[0][0][2][0][RTW89_ETSI][7] = 60,
- [0][0][2][0][RTW89_MKK][7] = 76,
- [0][0][2][0][RTW89_IC][7] = 80,
+ [0][0][2][0][RTW89_MKK][7] = 78,
+ [0][0][2][0][RTW89_IC][7] = 78,
[0][0][2][0][RTW89_ACMA][7] = 60,
- [0][0][2][0][RTW89_FCC][8] = 78,
+ [0][0][2][0][RTW89_FCC][8] = 68,
[0][0][2][0][RTW89_ETSI][8] = 60,
- [0][0][2][0][RTW89_MKK][8] = 76,
+ [0][0][2][0][RTW89_MKK][8] = 78,
[0][0][2][0][RTW89_IC][8] = 78,
[0][0][2][0][RTW89_ACMA][8] = 60,
- [0][0][2][0][RTW89_FCC][9] = 74,
+ [0][0][2][0][RTW89_FCC][9] = 64,
[0][0][2][0][RTW89_ETSI][9] = 60,
- [0][0][2][0][RTW89_MKK][9] = 76,
+ [0][0][2][0][RTW89_MKK][9] = 78,
[0][0][2][0][RTW89_IC][9] = 74,
[0][0][2][0][RTW89_ACMA][9] = 60,
- [0][0][2][0][RTW89_FCC][10] = 74,
+ [0][0][2][0][RTW89_FCC][10] = 64,
[0][0][2][0][RTW89_ETSI][10] = 60,
- [0][0][2][0][RTW89_MKK][10] = 76,
+ [0][0][2][0][RTW89_MKK][10] = 78,
[0][0][2][0][RTW89_IC][10] = 74,
[0][0][2][0][RTW89_ACMA][10] = 60,
- [0][0][2][0][RTW89_FCC][11] = 56,
+ [0][0][2][0][RTW89_FCC][11] = 46,
[0][0][2][0][RTW89_ETSI][11] = 60,
- [0][0][2][0][RTW89_MKK][11] = 76,
+ [0][0][2][0][RTW89_MKK][11] = 78,
[0][0][2][0][RTW89_IC][11] = 56,
[0][0][2][0][RTW89_ACMA][11] = 60,
- [0][0][2][0][RTW89_FCC][12] = 52,
+ [0][0][2][0][RTW89_FCC][12] = 42,
[0][0][2][0][RTW89_ETSI][12] = 60,
- [0][0][2][0][RTW89_MKK][12] = 76,
+ [0][0][2][0][RTW89_MKK][12] = 78,
[0][0][2][0][RTW89_IC][12] = 52,
[0][0][2][0][RTW89_ACMA][12] = 60,
[0][0][2][0][RTW89_FCC][13] = 127,
@@ -14503,69 +14503,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_MKK][13] = 127,
[0][0][2][0][RTW89_IC][13] = 127,
[0][0][2][0][RTW89_ACMA][13] = 127,
- [0][1][2][0][RTW89_FCC][0] = 60,
+ [0][1][2][0][RTW89_FCC][0] = 50,
[0][1][2][0][RTW89_ETSI][0] = 48,
- [0][1][2][0][RTW89_MKK][0] = 70,
+ [0][1][2][0][RTW89_MKK][0] = 68,
[0][1][2][0][RTW89_IC][0] = 60,
[0][1][2][0][RTW89_ACMA][0] = 48,
- [0][1][2][0][RTW89_FCC][1] = 60,
+ [0][1][2][0][RTW89_FCC][1] = 50,
[0][1][2][0][RTW89_ETSI][1] = 48,
- [0][1][2][0][RTW89_MKK][1] = 70,
+ [0][1][2][0][RTW89_MKK][1] = 68,
[0][1][2][0][RTW89_IC][1] = 60,
[0][1][2][0][RTW89_ACMA][1] = 48,
- [0][1][2][0][RTW89_FCC][2] = 64,
+ [0][1][2][0][RTW89_FCC][2] = 54,
[0][1][2][0][RTW89_ETSI][2] = 48,
- [0][1][2][0][RTW89_MKK][2] = 70,
+ [0][1][2][0][RTW89_MKK][2] = 68,
[0][1][2][0][RTW89_IC][2] = 64,
[0][1][2][0][RTW89_ACMA][2] = 48,
- [0][1][2][0][RTW89_FCC][3] = 68,
+ [0][1][2][0][RTW89_FCC][3] = 58,
[0][1][2][0][RTW89_ETSI][3] = 48,
- [0][1][2][0][RTW89_MKK][3] = 70,
+ [0][1][2][0][RTW89_MKK][3] = 68,
[0][1][2][0][RTW89_IC][3] = 68,
[0][1][2][0][RTW89_ACMA][3] = 48,
- [0][1][2][0][RTW89_FCC][4] = 74,
+ [0][1][2][0][RTW89_FCC][4] = 64,
[0][1][2][0][RTW89_ETSI][4] = 48,
- [0][1][2][0][RTW89_MKK][4] = 70,
+ [0][1][2][0][RTW89_MKK][4] = 68,
[0][1][2][0][RTW89_IC][4] = 74,
[0][1][2][0][RTW89_ACMA][4] = 48,
- [0][1][2][0][RTW89_FCC][5] = 80,
+ [0][1][2][0][RTW89_FCC][5] = 70,
[0][1][2][0][RTW89_ETSI][5] = 48,
- [0][1][2][0][RTW89_MKK][5] = 70,
- [0][1][2][0][RTW89_IC][5] = 80,
+ [0][1][2][0][RTW89_MKK][5] = 68,
+ [0][1][2][0][RTW89_IC][5] = 78,
[0][1][2][0][RTW89_ACMA][5] = 48,
- [0][1][2][0][RTW89_FCC][6] = 76,
+ [0][1][2][0][RTW89_FCC][6] = 66,
[0][1][2][0][RTW89_ETSI][6] = 48,
- [0][1][2][0][RTW89_MKK][6] = 70,
+ [0][1][2][0][RTW89_MKK][6] = 68,
[0][1][2][0][RTW89_IC][6] = 76,
[0][1][2][0][RTW89_ACMA][6] = 48,
- [0][1][2][0][RTW89_FCC][7] = 68,
+ [0][1][2][0][RTW89_FCC][7] = 58,
[0][1][2][0][RTW89_ETSI][7] = 48,
- [0][1][2][0][RTW89_MKK][7] = 70,
+ [0][1][2][0][RTW89_MKK][7] = 68,
[0][1][2][0][RTW89_IC][7] = 68,
[0][1][2][0][RTW89_ACMA][7] = 48,
- [0][1][2][0][RTW89_FCC][8] = 64,
+ [0][1][2][0][RTW89_FCC][8] = 54,
[0][1][2][0][RTW89_ETSI][8] = 48,
- [0][1][2][0][RTW89_MKK][8] = 70,
+ [0][1][2][0][RTW89_MKK][8] = 68,
[0][1][2][0][RTW89_IC][8] = 64,
[0][1][2][0][RTW89_ACMA][8] = 48,
- [0][1][2][0][RTW89_FCC][9] = 60,
+ [0][1][2][0][RTW89_FCC][9] = 50,
[0][1][2][0][RTW89_ETSI][9] = 48,
- [0][1][2][0][RTW89_MKK][9] = 70,
+ [0][1][2][0][RTW89_MKK][9] = 68,
[0][1][2][0][RTW89_IC][9] = 60,
[0][1][2][0][RTW89_ACMA][9] = 48,
- [0][1][2][0][RTW89_FCC][10] = 60,
+ [0][1][2][0][RTW89_FCC][10] = 50,
[0][1][2][0][RTW89_ETSI][10] = 48,
- [0][1][2][0][RTW89_MKK][10] = 70,
+ [0][1][2][0][RTW89_MKK][10] = 68,
[0][1][2][0][RTW89_IC][10] = 60,
[0][1][2][0][RTW89_ACMA][10] = 48,
- [0][1][2][0][RTW89_FCC][11] = 48,
+ [0][1][2][0][RTW89_FCC][11] = 38,
[0][1][2][0][RTW89_ETSI][11] = 48,
- [0][1][2][0][RTW89_MKK][11] = 70,
+ [0][1][2][0][RTW89_MKK][11] = 68,
[0][1][2][0][RTW89_IC][11] = 48,
[0][1][2][0][RTW89_ACMA][11] = 48,
- [0][1][2][0][RTW89_FCC][12] = 44,
+ [0][1][2][0][RTW89_FCC][12] = 34,
[0][1][2][0][RTW89_ETSI][12] = 48,
- [0][1][2][0][RTW89_MKK][12] = 70,
+ [0][1][2][0][RTW89_MKK][12] = 68,
[0][1][2][0][RTW89_IC][12] = 44,
[0][1][2][0][RTW89_ACMA][12] = 48,
[0][1][2][0][RTW89_FCC][13] = 127,
@@ -14573,69 +14573,69 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_MKK][13] = 127,
[0][1][2][0][RTW89_IC][13] = 127,
[0][1][2][0][RTW89_ACMA][13] = 127,
- [0][1][2][1][RTW89_FCC][0] = 60,
- [0][1][2][1][RTW89_ETSI][0] = 38,
- [0][1][2][1][RTW89_MKK][0] = 58,
+ [0][1][2][1][RTW89_FCC][0] = 50,
+ [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_ACMA][0] = 36,
- [0][1][2][1][RTW89_FCC][1] = 60,
- [0][1][2][1][RTW89_ETSI][1] = 38,
- [0][1][2][1][RTW89_MKK][1] = 58,
+ [0][1][2][1][RTW89_FCC][1] = 50,
+ [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_ACMA][1] = 36,
- [0][1][2][1][RTW89_FCC][2] = 64,
- [0][1][2][1][RTW89_ETSI][2] = 38,
- [0][1][2][1][RTW89_MKK][2] = 58,
+ [0][1][2][1][RTW89_FCC][2] = 54,
+ [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_ACMA][2] = 36,
- [0][1][2][1][RTW89_FCC][3] = 68,
- [0][1][2][1][RTW89_ETSI][3] = 38,
- [0][1][2][1][RTW89_MKK][3] = 58,
+ [0][1][2][1][RTW89_FCC][3] = 58,
+ [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_ACMA][3] = 36,
- [0][1][2][1][RTW89_FCC][4] = 74,
- [0][1][2][1][RTW89_ETSI][4] = 38,
- [0][1][2][1][RTW89_MKK][4] = 58,
+ [0][1][2][1][RTW89_FCC][4] = 64,
+ [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_ACMA][4] = 36,
- [0][1][2][1][RTW89_FCC][5] = 80,
- [0][1][2][1][RTW89_ETSI][5] = 38,
- [0][1][2][1][RTW89_MKK][5] = 58,
- [0][1][2][1][RTW89_IC][5] = 80,
+ [0][1][2][1][RTW89_FCC][5] = 70,
+ [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_ACMA][5] = 36,
- [0][1][2][1][RTW89_FCC][6] = 76,
- [0][1][2][1][RTW89_ETSI][6] = 38,
- [0][1][2][1][RTW89_MKK][6] = 58,
+ [0][1][2][1][RTW89_FCC][6] = 66,
+ [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_ACMA][6] = 36,
- [0][1][2][1][RTW89_FCC][7] = 68,
- [0][1][2][1][RTW89_ETSI][7] = 38,
- [0][1][2][1][RTW89_MKK][7] = 58,
+ [0][1][2][1][RTW89_FCC][7] = 58,
+ [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_ACMA][7] = 36,
- [0][1][2][1][RTW89_FCC][8] = 64,
- [0][1][2][1][RTW89_ETSI][8] = 38,
- [0][1][2][1][RTW89_MKK][8] = 58,
+ [0][1][2][1][RTW89_FCC][8] = 54,
+ [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_ACMA][8] = 36,
- [0][1][2][1][RTW89_FCC][9] = 60,
- [0][1][2][1][RTW89_ETSI][9] = 38,
- [0][1][2][1][RTW89_MKK][9] = 58,
+ [0][1][2][1][RTW89_FCC][9] = 50,
+ [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_ACMA][9] = 36,
- [0][1][2][1][RTW89_FCC][10] = 60,
- [0][1][2][1][RTW89_ETSI][10] = 38,
- [0][1][2][1][RTW89_MKK][10] = 58,
+ [0][1][2][1][RTW89_FCC][10] = 50,
+ [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_ACMA][10] = 36,
- [0][1][2][1][RTW89_FCC][11] = 48,
- [0][1][2][1][RTW89_ETSI][11] = 38,
- [0][1][2][1][RTW89_MKK][11] = 58,
+ [0][1][2][1][RTW89_FCC][11] = 38,
+ [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_ACMA][11] = 36,
- [0][1][2][1][RTW89_FCC][12] = 44,
- [0][1][2][1][RTW89_ETSI][12] = 38,
- [0][1][2][1][RTW89_MKK][12] = 58,
+ [0][1][2][1][RTW89_FCC][12] = 34,
+ [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_ACMA][12] = 36,
[0][1][2][1][RTW89_FCC][13] = 127,
@@ -14653,49 +14653,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_MKK][1] = 127,
[1][0][2][0][RTW89_IC][1] = 127,
[1][0][2][0][RTW89_ACMA][1] = 127,
- [1][0][2][0][RTW89_FCC][2] = 72,
+ [1][0][2][0][RTW89_FCC][2] = 62,
[1][0][2][0][RTW89_ETSI][2] = 60,
- [1][0][2][0][RTW89_MKK][2] = 72,
+ [1][0][2][0][RTW89_MKK][2] = 74,
[1][0][2][0][RTW89_IC][2] = 72,
[1][0][2][0][RTW89_ACMA][2] = 60,
- [1][0][2][0][RTW89_FCC][3] = 72,
+ [1][0][2][0][RTW89_FCC][3] = 62,
[1][0][2][0][RTW89_ETSI][3] = 60,
- [1][0][2][0][RTW89_MKK][3] = 72,
+ [1][0][2][0][RTW89_MKK][3] = 74,
[1][0][2][0][RTW89_IC][3] = 72,
[1][0][2][0][RTW89_ACMA][3] = 60,
- [1][0][2][0][RTW89_FCC][4] = 74,
+ [1][0][2][0][RTW89_FCC][4] = 64,
[1][0][2][0][RTW89_ETSI][4] = 60,
- [1][0][2][0][RTW89_MKK][4] = 72,
+ [1][0][2][0][RTW89_MKK][4] = 74,
[1][0][2][0][RTW89_IC][4] = 74,
[1][0][2][0][RTW89_ACMA][4] = 60,
- [1][0][2][0][RTW89_FCC][5] = 74,
+ [1][0][2][0][RTW89_FCC][5] = 64,
[1][0][2][0][RTW89_ETSI][5] = 60,
- [1][0][2][0][RTW89_MKK][5] = 72,
+ [1][0][2][0][RTW89_MKK][5] = 74,
[1][0][2][0][RTW89_IC][5] = 74,
[1][0][2][0][RTW89_ACMA][5] = 60,
- [1][0][2][0][RTW89_FCC][6] = 74,
+ [1][0][2][0][RTW89_FCC][6] = 64,
[1][0][2][0][RTW89_ETSI][6] = 60,
- [1][0][2][0][RTW89_MKK][6] = 72,
+ [1][0][2][0][RTW89_MKK][6] = 74,
[1][0][2][0][RTW89_IC][6] = 74,
[1][0][2][0][RTW89_ACMA][6] = 60,
- [1][0][2][0][RTW89_FCC][7] = 70,
+ [1][0][2][0][RTW89_FCC][7] = 60,
[1][0][2][0][RTW89_ETSI][7] = 60,
- [1][0][2][0][RTW89_MKK][7] = 72,
+ [1][0][2][0][RTW89_MKK][7] = 74,
[1][0][2][0][RTW89_IC][7] = 70,
[1][0][2][0][RTW89_ACMA][7] = 60,
- [1][0][2][0][RTW89_FCC][8] = 70,
+ [1][0][2][0][RTW89_FCC][8] = 60,
[1][0][2][0][RTW89_ETSI][8] = 60,
- [1][0][2][0][RTW89_MKK][8] = 72,
+ [1][0][2][0][RTW89_MKK][8] = 74,
[1][0][2][0][RTW89_IC][8] = 70,
[1][0][2][0][RTW89_ACMA][8] = 60,
- [1][0][2][0][RTW89_FCC][9] = 70,
+ [1][0][2][0][RTW89_FCC][9] = 60,
[1][0][2][0][RTW89_ETSI][9] = 60,
- [1][0][2][0][RTW89_MKK][9] = 72,
+ [1][0][2][0][RTW89_MKK][9] = 74,
[1][0][2][0][RTW89_IC][9] = 70,
[1][0][2][0][RTW89_ACMA][9] = 60,
- [1][0][2][0][RTW89_FCC][10] = 68,
+ [1][0][2][0][RTW89_FCC][10] = 58,
[1][0][2][0][RTW89_ETSI][10] = 60,
- [1][0][2][0][RTW89_MKK][10] = 72,
+ [1][0][2][0][RTW89_MKK][10] = 74,
[1][0][2][0][RTW89_IC][10] = 68,
[1][0][2][0][RTW89_ACMA][10] = 60,
[1][0][2][0][RTW89_FCC][11] = 127,
@@ -14723,49 +14723,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_MKK][1] = 127,
[1][1][2][0][RTW89_IC][1] = 127,
[1][1][2][0][RTW89_ACMA][1] = 127,
- [1][1][2][0][RTW89_FCC][2] = 56,
+ [1][1][2][0][RTW89_FCC][2] = 46,
[1][1][2][0][RTW89_ETSI][2] = 48,
- [1][1][2][0][RTW89_MKK][2] = 70,
+ [1][1][2][0][RTW89_MKK][2] = 68,
[1][1][2][0][RTW89_IC][2] = 56,
[1][1][2][0][RTW89_ACMA][2] = 48,
- [1][1][2][0][RTW89_FCC][3] = 56,
+ [1][1][2][0][RTW89_FCC][3] = 46,
[1][1][2][0][RTW89_ETSI][3] = 48,
- [1][1][2][0][RTW89_MKK][3] = 70,
+ [1][1][2][0][RTW89_MKK][3] = 68,
[1][1][2][0][RTW89_IC][3] = 56,
[1][1][2][0][RTW89_ACMA][3] = 48,
- [1][1][2][0][RTW89_FCC][4] = 60,
+ [1][1][2][0][RTW89_FCC][4] = 50,
[1][1][2][0][RTW89_ETSI][4] = 48,
- [1][1][2][0][RTW89_MKK][4] = 70,
+ [1][1][2][0][RTW89_MKK][4] = 68,
[1][1][2][0][RTW89_IC][4] = 60,
[1][1][2][0][RTW89_ACMA][4] = 48,
- [1][1][2][0][RTW89_FCC][5] = 68,
+ [1][1][2][0][RTW89_FCC][5] = 58,
[1][1][2][0][RTW89_ETSI][5] = 48,
- [1][1][2][0][RTW89_MKK][5] = 70,
+ [1][1][2][0][RTW89_MKK][5] = 68,
[1][1][2][0][RTW89_IC][5] = 68,
[1][1][2][0][RTW89_ACMA][5] = 48,
- [1][1][2][0][RTW89_FCC][6] = 60,
+ [1][1][2][0][RTW89_FCC][6] = 50,
[1][1][2][0][RTW89_ETSI][6] = 48,
- [1][1][2][0][RTW89_MKK][6] = 70,
+ [1][1][2][0][RTW89_MKK][6] = 68,
[1][1][2][0][RTW89_IC][6] = 60,
[1][1][2][0][RTW89_ACMA][6] = 48,
- [1][1][2][0][RTW89_FCC][7] = 56,
+ [1][1][2][0][RTW89_FCC][7] = 46,
[1][1][2][0][RTW89_ETSI][7] = 48,
- [1][1][2][0][RTW89_MKK][7] = 70,
+ [1][1][2][0][RTW89_MKK][7] = 68,
[1][1][2][0][RTW89_IC][7] = 56,
[1][1][2][0][RTW89_ACMA][7] = 48,
- [1][1][2][0][RTW89_FCC][8] = 56,
+ [1][1][2][0][RTW89_FCC][8] = 46,
[1][1][2][0][RTW89_ETSI][8] = 48,
- [1][1][2][0][RTW89_MKK][8] = 70,
+ [1][1][2][0][RTW89_MKK][8] = 68,
[1][1][2][0][RTW89_IC][8] = 56,
[1][1][2][0][RTW89_ACMA][8] = 48,
- [1][1][2][0][RTW89_FCC][9] = 44,
+ [1][1][2][0][RTW89_FCC][9] = 34,
[1][1][2][0][RTW89_ETSI][9] = 48,
- [1][1][2][0][RTW89_MKK][9] = 70,
+ [1][1][2][0][RTW89_MKK][9] = 68,
[1][1][2][0][RTW89_IC][9] = 44,
[1][1][2][0][RTW89_ACMA][9] = 48,
- [1][1][2][0][RTW89_FCC][10] = 40,
+ [1][1][2][0][RTW89_FCC][10] = 30,
[1][1][2][0][RTW89_ETSI][10] = 48,
- [1][1][2][0][RTW89_MKK][10] = 70,
+ [1][1][2][0][RTW89_MKK][10] = 68,
[1][1][2][0][RTW89_IC][10] = 40,
[1][1][2][0][RTW89_ACMA][10] = 48,
[1][1][2][0][RTW89_FCC][11] = 127,
@@ -14793,49 +14793,49 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_MKK][1] = 127,
[1][1][2][1][RTW89_IC][1] = 127,
[1][1][2][1][RTW89_ACMA][1] = 127,
- [1][1][2][1][RTW89_FCC][2] = 56,
- [1][1][2][1][RTW89_ETSI][2] = 38,
- [1][1][2][1][RTW89_MKK][2] = 58,
+ [1][1][2][1][RTW89_FCC][2] = 46,
+ [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_ACMA][2] = 36,
- [1][1][2][1][RTW89_FCC][3] = 56,
- [1][1][2][1][RTW89_ETSI][3] = 38,
- [1][1][2][1][RTW89_MKK][3] = 58,
+ [1][1][2][1][RTW89_FCC][3] = 46,
+ [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_ACMA][3] = 36,
- [1][1][2][1][RTW89_FCC][4] = 60,
- [1][1][2][1][RTW89_ETSI][4] = 38,
- [1][1][2][1][RTW89_MKK][4] = 58,
+ [1][1][2][1][RTW89_FCC][4] = 50,
+ [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_ACMA][4] = 36,
- [1][1][2][1][RTW89_FCC][5] = 68,
- [1][1][2][1][RTW89_ETSI][5] = 38,
- [1][1][2][1][RTW89_MKK][5] = 58,
+ [1][1][2][1][RTW89_FCC][5] = 58,
+ [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_ACMA][5] = 36,
- [1][1][2][1][RTW89_FCC][6] = 60,
- [1][1][2][1][RTW89_ETSI][6] = 38,
- [1][1][2][1][RTW89_MKK][6] = 58,
+ [1][1][2][1][RTW89_FCC][6] = 50,
+ [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_ACMA][6] = 36,
- [1][1][2][1][RTW89_FCC][7] = 56,
- [1][1][2][1][RTW89_ETSI][7] = 38,
- [1][1][2][1][RTW89_MKK][7] = 58,
+ [1][1][2][1][RTW89_FCC][7] = 46,
+ [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_ACMA][7] = 36,
- [1][1][2][1][RTW89_FCC][8] = 56,
- [1][1][2][1][RTW89_ETSI][8] = 38,
- [1][1][2][1][RTW89_MKK][8] = 58,
+ [1][1][2][1][RTW89_FCC][8] = 46,
+ [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_ACMA][8] = 36,
- [1][1][2][1][RTW89_FCC][9] = 44,
- [1][1][2][1][RTW89_ETSI][9] = 38,
- [1][1][2][1][RTW89_MKK][9] = 58,
+ [1][1][2][1][RTW89_FCC][9] = 34,
+ [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_ACMA][9] = 36,
- [1][1][2][1][RTW89_FCC][10] = 40,
- [1][1][2][1][RTW89_ETSI][10] = 38,
- [1][1][2][1][RTW89_MKK][10] = 58,
+ [1][1][2][1][RTW89_FCC][10] = 30,
+ [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_ACMA][10] = 36,
[1][1][2][1][RTW89_FCC][11] = 127,
@@ -14871,21 +14871,21 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[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][25] = 60,
- [0][0][1][0][RTW89_WW][27] = 60,
- [0][0][1][0][RTW89_WW][29] = 60,
+ [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][35] = 60,
- [0][0][1][0][RTW89_WW][37] = 78,
+ [0][0][1][0][RTW89_WW][37] = 70,
[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] = 80,
- [0][0][1][0][RTW89_WW][50] = 80,
- [0][0][1][0][RTW89_WW][52] = 80,
+ [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,
@@ -14899,26 +14899,26 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[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][1][1][0][RTW89_WW][25] = 48,
- [0][1][1][0][RTW89_WW][27] = 48,
- [0][1][1][0][RTW89_WW][29] = 48,
+ [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] = 70,
+ [0][1][1][0][RTW89_WW][37] = 60,
[0][1][1][0][RTW89_WW][38] = 18,
[0][1][1][0][RTW89_WW][40] = 16,
[0][1][1][0][RTW89_WW][42] = 18,
[0][1][1][0][RTW89_WW][44] = 16,
[0][1][1][0][RTW89_WW][46] = 18,
- [0][1][1][0][RTW89_WW][48] = 58,
- [0][1][1][0][RTW89_WW][50] = 58,
- [0][1][1][0][RTW89_WW][52] = 58,
+ [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] = 62,
- [0][0][2][0][RTW89_WW][8] = 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,
@@ -14927,26 +14927,26 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[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][25] = 62,
- [0][0][2][0][RTW89_WW][27] = 62,
- [0][0][2][0][RTW89_WW][29] = 62,
+ [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] = 78,
+ [0][0][2][0][RTW89_WW][37] = 70,
[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] = 80,
- [0][0][2][0][RTW89_WW][50] = 80,
- [0][0][2][0][RTW89_WW][52] = 80,
+ [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] = 50,
+ [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,
@@ -14955,21 +14955,21 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[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][1][2][0][RTW89_WW][25] = 50,
- [0][1][2][0][RTW89_WW][27] = 50,
- [0][1][2][0][RTW89_WW][29] = 50,
+ [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] = 72,
+ [0][1][2][0][RTW89_WW][37] = 62,
[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] = 60,
- [0][1][2][0][RTW89_WW][50] = 60,
- [0][1][2][0][RTW89_WW][52] = 60,
+ [0][1][2][0][RTW89_WW][48] = 50,
+ [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,
@@ -14983,1149 +14983,1149 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[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][1][RTW89_WW][25] = 42,
- [0][1][2][1][RTW89_WW][27] = 42,
- [0][1][2][1][RTW89_WW][29] = 42,
+ [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] = 70,
- [0][1][2][1][RTW89_WW][38] = 8,
- [0][1][2][1][RTW89_WW][40] = 8,
- [0][1][2][1][RTW89_WW][42] = 8,
- [0][1][2][1][RTW89_WW][44] = 8,
- [0][1][2][1][RTW89_WW][46] = 8,
- [0][1][2][1][RTW89_WW][48] = 60,
- [0][1][2][1][RTW89_WW][50] = 60,
- [0][1][2][1][RTW89_WW][52] = 60,
- [1][0][2][0][RTW89_WW][1] = 66,
+ [0][1][2][1][RTW89_WW][37] = 60,
+ [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][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] = 66,
- [1][0][2][0][RTW89_WW][16] = 66,
+ [1][0][2][0][RTW89_WW][13] = 58,
+ [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][28] = 66,
[1][0][2][0][RTW89_WW][32] = 66,
- [1][0][2][0][RTW89_WW][36] = 76,
+ [1][0][2][0][RTW89_WW][36] = 66,
[1][0][2][0][RTW89_WW][39] = 30,
[1][0][2][0][RTW89_WW][43] = 30,
- [1][0][2][0][RTW89_WW][47] = 80,
- [1][0][2][0][RTW89_WW][51] = 72,
- [1][1][2][0][RTW89_WW][1] = 54,
- [1][1][2][0][RTW89_WW][5] = 54,
- [1][1][2][0][RTW89_WW][9] = 54,
- [1][1][2][0][RTW89_WW][13] = 54,
- [1][1][2][0][RTW89_WW][16] = 54,
+ [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][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] = 72,
+ [1][1][2][0][RTW89_WW][36] = 66,
[1][1][2][0][RTW89_WW][39] = 18,
[1][1][2][0][RTW89_WW][43] = 18,
- [1][1][2][0][RTW89_WW][47] = 70,
- [1][1][2][0][RTW89_WW][51] = 68,
- [1][1][2][1][RTW89_WW][1] = 42,
- [1][1][2][1][RTW89_WW][5] = 42,
- [1][1][2][1][RTW89_WW][9] = 42,
- [1][1][2][1][RTW89_WW][13] = 42,
- [1][1][2][1][RTW89_WW][16] = 42,
- [1][1][2][1][RTW89_WW][20] = 42,
- [1][1][2][1][RTW89_WW][24] = 42,
- [1][1][2][1][RTW89_WW][28] = 42,
- [1][1][2][1][RTW89_WW][32] = 42,
- [1][1][2][1][RTW89_WW][36] = 70,
- [1][1][2][1][RTW89_WW][39] = 8,
- [1][1][2][1][RTW89_WW][43] = 8,
- [1][1][2][1][RTW89_WW][47] = 70,
- [1][1][2][1][RTW89_WW][51] = 68,
- [2][0][2][0][RTW89_WW][3] = 64,
- [2][0][2][0][RTW89_WW][11] = 66,
- [2][0][2][0][RTW89_WW][18] = 64,
- [2][0][2][0][RTW89_WW][26] = 66,
- [2][0][2][0][RTW89_WW][34] = 72,
+ [1][1][2][0][RTW89_WW][47] = 60,
+ [1][1][2][0][RTW89_WW][51] = 58,
+ [1][1][2][1][RTW89_WW][1] = 40,
+ [1][1][2][1][RTW89_WW][5] = 40,
+ [1][1][2][1][RTW89_WW][9] = 40,
+ [1][1][2][1][RTW89_WW][13] = 40,
+ [1][1][2][1][RTW89_WW][16] = 40,
+ [1][1][2][1][RTW89_WW][20] = 40,
+ [1][1][2][1][RTW89_WW][24] = 40,
+ [1][1][2][1][RTW89_WW][28] = 40,
+ [1][1][2][1][RTW89_WW][32] = 40,
+ [1][1][2][1][RTW89_WW][36] = 60,
+ [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,
+ [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] = 66,
- [2][1][2][0][RTW89_WW][3] = 54,
- [2][1][2][0][RTW89_WW][11] = 54,
- [2][1][2][0][RTW89_WW][18] = 54,
+ [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] = 72,
+ [2][1][2][0][RTW89_WW][34] = 60,
[2][1][2][0][RTW89_WW][41] = 18,
- [2][1][2][0][RTW89_WW][49] = 60,
- [2][1][2][1][RTW89_WW][3] = 42,
- [2][1][2][1][RTW89_WW][11] = 42,
- [2][1][2][1][RTW89_WW][18] = 42,
- [2][1][2][1][RTW89_WW][26] = 44,
- [2][1][2][1][RTW89_WW][34] = 70,
- [2][1][2][1][RTW89_WW][41] = 8,
- [2][1][2][1][RTW89_WW][49] = 60,
- [3][0][2][0][RTW89_WW][7] = 56,
- [3][0][2][0][RTW89_WW][22] = 56,
- [3][0][2][0][RTW89_WW][45] = 56,
- [3][1][2][0][RTW89_WW][7] = 44,
- [3][1][2][0][RTW89_WW][22] = 44,
- [3][1][2][0][RTW89_WW][45] = 44,
- [3][1][2][1][RTW89_WW][7] = 32,
- [3][1][2][1][RTW89_WW][22] = 32,
- [3][1][2][1][RTW89_WW][45] = 32,
- [0][0][1][0][RTW89_FCC][0] = 80,
- [0][0][1][0][RTW89_ETSI][0] = 60,
- [0][0][1][0][RTW89_MKK][0] = 62,
+ [2][1][2][0][RTW89_WW][49] = 50,
+ [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] = 42,
+ [2][1][2][1][RTW89_WW][34] = 60,
+ [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,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][2] = 60,
- [0][0][1][0][RTW89_MKK][2] = 62,
+ [0][0][1][0][RTW89_FCC][2] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][4] = 60,
- [0][0][1][0][RTW89_MKK][4] = 62,
+ [0][0][1][0][RTW89_FCC][4] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][6] = 60,
- [0][0][1][0][RTW89_MKK][6] = 62,
+ [0][0][1][0][RTW89_FCC][6] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][8] = 60,
- [0][0][1][0][RTW89_MKK][8] = 64,
+ [0][0][1][0][RTW89_FCC][8] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][10] = 60,
- [0][0][1][0][RTW89_MKK][10] = 64,
+ [0][0][1][0][RTW89_FCC][10] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][12] = 60,
- [0][0][1][0][RTW89_MKK][12] = 64,
+ [0][0][1][0][RTW89_FCC][12] = 70,
+ [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_FCC][14] = 80,
- [0][0][1][0][RTW89_ETSI][14] = 60,
- [0][0][1][0][RTW89_MKK][14] = 62,
+ [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] = 78,
- [0][0][1][0][RTW89_ETSI][15] = 60,
- [0][0][1][0][RTW89_MKK][15] = 78,
- [0][0][1][0][RTW89_IC][15] = 78,
+ [0][0][1][0][RTW89_FCC][15] = 68,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][17] = 60,
- [0][0][1][0][RTW89_MKK][17] = 78,
- [0][0][1][0][RTW89_IC][17] = 80,
+ [0][0][1][0][RTW89_FCC][17] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][19] = 60,
- [0][0][1][0][RTW89_MKK][19] = 78,
- [0][0][1][0][RTW89_IC][19] = 80,
+ [0][0][1][0][RTW89_FCC][19] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][21] = 60,
- [0][0][1][0][RTW89_MKK][21] = 78,
- [0][0][1][0][RTW89_IC][21] = 80,
+ [0][0][1][0][RTW89_FCC][21] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][23] = 60,
- [0][0][1][0][RTW89_MKK][23] = 78,
- [0][0][1][0][RTW89_IC][23] = 80,
+ [0][0][1][0][RTW89_FCC][23] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][25] = 60,
- [0][0][1][0][RTW89_MKK][25] = 78,
+ [0][0][1][0][RTW89_FCC][25] = 70,
+ [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_ACMA][25] = 127,
- [0][0][1][0][RTW89_FCC][27] = 80,
- [0][0][1][0][RTW89_ETSI][27] = 60,
- [0][0][1][0][RTW89_MKK][27] = 78,
+ [0][0][1][0][RTW89_FCC][27] = 70,
+ [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_ACMA][27] = 127,
- [0][0][1][0][RTW89_FCC][29] = 80,
- [0][0][1][0][RTW89_ETSI][29] = 60,
- [0][0][1][0][RTW89_MKK][29] = 78,
+ [0][0][1][0][RTW89_FCC][29] = 70,
+ [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_ACMA][29] = 127,
- [0][0][1][0][RTW89_FCC][31] = 80,
- [0][0][1][0][RTW89_ETSI][31] = 60,
- [0][0][1][0][RTW89_MKK][31] = 78,
- [0][0][1][0][RTW89_IC][31] = 80,
+ [0][0][1][0][RTW89_FCC][31] = 70,
+ [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] = 80,
- [0][0][1][0][RTW89_ETSI][33] = 60,
- [0][0][1][0][RTW89_MKK][33] = 78,
- [0][0][1][0][RTW89_IC][33] = 80,
+ [0][0][1][0][RTW89_FCC][33] = 70,
+ [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] = 72,
- [0][0][1][0][RTW89_ETSI][35] = 60,
- [0][0][1][0][RTW89_MKK][35] = 78,
- [0][0][1][0][RTW89_IC][35] = 72,
+ [0][0][1][0][RTW89_FCC][35] = 62,
+ [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] = 80,
+ [0][0][1][0][RTW89_FCC][37] = 70,
[0][0][1][0][RTW89_ETSI][37] = 127,
- [0][0][1][0][RTW89_MKK][37] = 78,
- [0][0][1][0][RTW89_IC][37] = 80,
- [0][0][1][0][RTW89_ACMA][37] = 78,
- [0][0][1][0][RTW89_FCC][38] = 80,
+ [0][0][1][0][RTW89_MKK][37] = 70,
+ [0][0][1][0][RTW89_IC][37] = 70,
+ [0][0][1][0][RTW89_ACMA][37] = 70,
+ [0][0][1][0][RTW89_FCC][38] = 70,
[0][0][1][0][RTW89_ETSI][38] = 30,
[0][0][1][0][RTW89_MKK][38] = 127,
- [0][0][1][0][RTW89_IC][38] = 80,
- [0][0][1][0][RTW89_ACMA][38] = 78,
- [0][0][1][0][RTW89_FCC][40] = 80,
+ [0][0][1][0][RTW89_IC][38] = 70,
+ [0][0][1][0][RTW89_ACMA][38] = 70,
+ [0][0][1][0][RTW89_FCC][40] = 70,
[0][0][1][0][RTW89_ETSI][40] = 30,
[0][0][1][0][RTW89_MKK][40] = 127,
- [0][0][1][0][RTW89_IC][40] = 80,
- [0][0][1][0][RTW89_ACMA][40] = 78,
- [0][0][1][0][RTW89_FCC][42] = 80,
+ [0][0][1][0][RTW89_IC][40] = 70,
+ [0][0][1][0][RTW89_ACMA][40] = 70,
+ [0][0][1][0][RTW89_FCC][42] = 70,
[0][0][1][0][RTW89_ETSI][42] = 30,
[0][0][1][0][RTW89_MKK][42] = 127,
- [0][0][1][0][RTW89_IC][42] = 80,
- [0][0][1][0][RTW89_ACMA][42] = 78,
- [0][0][1][0][RTW89_FCC][44] = 80,
+ [0][0][1][0][RTW89_IC][42] = 70,
+ [0][0][1][0][RTW89_ACMA][42] = 70,
+ [0][0][1][0][RTW89_FCC][44] = 70,
[0][0][1][0][RTW89_ETSI][44] = 30,
[0][0][1][0][RTW89_MKK][44] = 127,
- [0][0][1][0][RTW89_IC][44] = 80,
- [0][0][1][0][RTW89_ACMA][44] = 78,
- [0][0][1][0][RTW89_FCC][46] = 80,
+ [0][0][1][0][RTW89_IC][44] = 70,
+ [0][0][1][0][RTW89_ACMA][44] = 70,
+ [0][0][1][0][RTW89_FCC][46] = 70,
[0][0][1][0][RTW89_ETSI][46] = 30,
[0][0][1][0][RTW89_MKK][46] = 127,
- [0][0][1][0][RTW89_IC][46] = 80,
- [0][0][1][0][RTW89_ACMA][46] = 78,
- [0][0][1][0][RTW89_FCC][48] = 80,
+ [0][0][1][0][RTW89_IC][46] = 70,
+ [0][0][1][0][RTW89_ACMA][46] = 70,
+ [0][0][1][0][RTW89_FCC][48] = 70,
[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_ACMA][48] = 127,
- [0][0][1][0][RTW89_FCC][50] = 80,
+ [0][0][1][0][RTW89_FCC][50] = 70,
[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_ACMA][50] = 127,
- [0][0][1][0][RTW89_FCC][52] = 80,
+ [0][0][1][0][RTW89_FCC][52] = 70,
[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_ACMA][52] = 127,
- [0][1][1][0][RTW89_FCC][0] = 70,
- [0][1][1][0][RTW89_ETSI][0] = 48,
- [0][1][1][0][RTW89_MKK][0] = 50,
+ [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_FCC][2] = 70,
- [0][1][1][0][RTW89_ETSI][2] = 48,
- [0][1][1][0][RTW89_MKK][2] = 50,
+ [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_FCC][4] = 70,
- [0][1][1][0][RTW89_ETSI][4] = 48,
- [0][1][1][0][RTW89_MKK][4] = 50,
+ [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_FCC][6] = 70,
- [0][1][1][0][RTW89_ETSI][6] = 48,
- [0][1][1][0][RTW89_MKK][6] = 50,
+ [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] = 70,
- [0][1][1][0][RTW89_ETSI][8] = 48,
- [0][1][1][0][RTW89_MKK][8] = 50,
+ [0][1][1][0][RTW89_FCC][8] = 60,
+ [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] = 70,
- [0][1][1][0][RTW89_ETSI][10] = 48,
- [0][1][1][0][RTW89_MKK][10] = 50,
+ [0][1][1][0][RTW89_FCC][10] = 60,
+ [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] = 70,
- [0][1][1][0][RTW89_ETSI][12] = 48,
- [0][1][1][0][RTW89_MKK][12] = 50,
+ [0][1][1][0][RTW89_FCC][12] = 60,
+ [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_FCC][14] = 70,
- [0][1][1][0][RTW89_ETSI][14] = 48,
- [0][1][1][0][RTW89_MKK][14] = 50,
+ [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] = 68,
- [0][1][1][0][RTW89_ETSI][15] = 48,
+ [0][1][1][0][RTW89_FCC][15] = 58,
+ [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_FCC][17] = 70,
- [0][1][1][0][RTW89_ETSI][17] = 48,
- [0][1][1][0][RTW89_MKK][17] = 72,
+ [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_FCC][19] = 70,
- [0][1][1][0][RTW89_ETSI][19] = 48,
- [0][1][1][0][RTW89_MKK][19] = 72,
+ [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_FCC][21] = 70,
- [0][1][1][0][RTW89_ETSI][21] = 48,
- [0][1][1][0][RTW89_MKK][21] = 72,
+ [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_FCC][23] = 70,
- [0][1][1][0][RTW89_ETSI][23] = 48,
- [0][1][1][0][RTW89_MKK][23] = 72,
+ [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_FCC][25] = 70,
- [0][1][1][0][RTW89_ETSI][25] = 48,
+ [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_ACMA][25] = 127,
- [0][1][1][0][RTW89_FCC][27] = 70,
- [0][1][1][0][RTW89_ETSI][27] = 48,
- [0][1][1][0][RTW89_MKK][27] = 72,
+ [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_ACMA][27] = 127,
- [0][1][1][0][RTW89_FCC][29] = 70,
- [0][1][1][0][RTW89_ETSI][29] = 48,
- [0][1][1][0][RTW89_MKK][29] = 72,
+ [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_ACMA][29] = 127,
- [0][1][1][0][RTW89_FCC][31] = 70,
- [0][1][1][0][RTW89_ETSI][31] = 48,
- [0][1][1][0][RTW89_MKK][31] = 72,
+ [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_FCC][33] = 70,
- [0][1][1][0][RTW89_ETSI][33] = 48,
- [0][1][1][0][RTW89_MKK][33] = 72,
+ [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] = 68,
- [0][1][1][0][RTW89_ETSI][35] = 48,
- [0][1][1][0][RTW89_MKK][35] = 72,
+ [0][1][1][0][RTW89_FCC][35] = 58,
+ [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] = 70,
+ [0][1][1][0][RTW89_FCC][37] = 60,
[0][1][1][0][RTW89_ETSI][37] = 127,
- [0][1][1][0][RTW89_MKK][37] = 72,
+ [0][1][1][0][RTW89_MKK][37] = 70,
[0][1][1][0][RTW89_IC][37] = 70,
- [0][1][1][0][RTW89_ACMA][37] = 72,
- [0][1][1][0][RTW89_FCC][38] = 80,
+ [0][1][1][0][RTW89_ACMA][37] = 70,
+ [0][1][1][0][RTW89_FCC][38] = 70,
[0][1][1][0][RTW89_ETSI][38] = 18,
[0][1][1][0][RTW89_MKK][38] = 127,
- [0][1][1][0][RTW89_IC][38] = 80,
- [0][1][1][0][RTW89_ACMA][38] = 74,
- [0][1][1][0][RTW89_FCC][40] = 80,
+ [0][1][1][0][RTW89_IC][38] = 70,
+ [0][1][1][0][RTW89_ACMA][38] = 70,
+ [0][1][1][0][RTW89_FCC][40] = 70,
[0][1][1][0][RTW89_ETSI][40] = 18,
[0][1][1][0][RTW89_MKK][40] = 127,
- [0][1][1][0][RTW89_IC][40] = 80,
+ [0][1][1][0][RTW89_IC][40] = 70,
[0][1][1][0][RTW89_ACMA][40] = 16,
- [0][1][1][0][RTW89_FCC][42] = 80,
+ [0][1][1][0][RTW89_FCC][42] = 70,
[0][1][1][0][RTW89_ETSI][42] = 18,
[0][1][1][0][RTW89_MKK][42] = 127,
- [0][1][1][0][RTW89_IC][42] = 80,
- [0][1][1][0][RTW89_ACMA][42] = 78,
- [0][1][1][0][RTW89_FCC][44] = 80,
+ [0][1][1][0][RTW89_IC][42] = 70,
+ [0][1][1][0][RTW89_ACMA][42] = 70,
+ [0][1][1][0][RTW89_FCC][44] = 70,
[0][1][1][0][RTW89_ETSI][44] = 18,
[0][1][1][0][RTW89_MKK][44] = 127,
- [0][1][1][0][RTW89_IC][44] = 80,
+ [0][1][1][0][RTW89_IC][44] = 70,
[0][1][1][0][RTW89_ACMA][44] = 16,
- [0][1][1][0][RTW89_FCC][46] = 80,
+ [0][1][1][0][RTW89_FCC][46] = 70,
[0][1][1][0][RTW89_ETSI][46] = 18,
[0][1][1][0][RTW89_MKK][46] = 127,
- [0][1][1][0][RTW89_IC][46] = 80,
- [0][1][1][0][RTW89_ACMA][46] = 78,
- [0][1][1][0][RTW89_FCC][48] = 58,
+ [0][1][1][0][RTW89_IC][46] = 70,
+ [0][1][1][0][RTW89_ACMA][46] = 70,
+ [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_ACMA][48] = 127,
- [0][1][1][0][RTW89_FCC][50] = 58,
+ [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_ACMA][50] = 127,
- [0][1][1][0][RTW89_FCC][52] = 58,
+ [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_ACMA][52] = 127,
- [0][0][2][0][RTW89_FCC][0] = 80,
- [0][0][2][0][RTW89_ETSI][0] = 62,
- [0][0][2][0][RTW89_MKK][0] = 64,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][2] = 62,
- [0][0][2][0][RTW89_MKK][2] = 64,
+ [0][0][2][0][RTW89_FCC][2] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][4] = 62,
- [0][0][2][0][RTW89_MKK][4] = 64,
+ [0][0][2][0][RTW89_FCC][4] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][6] = 62,
- [0][0][2][0][RTW89_MKK][6] = 64,
+ [0][0][2][0][RTW89_FCC][6] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][8] = 62,
- [0][0][2][0][RTW89_MKK][8] = 64,
+ [0][0][2][0][RTW89_FCC][8] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][10] = 62,
- [0][0][2][0][RTW89_MKK][10] = 64,
+ [0][0][2][0][RTW89_FCC][10] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][12] = 62,
- [0][0][2][0][RTW89_MKK][12] = 64,
+ [0][0][2][0][RTW89_FCC][12] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][14] = 62,
- [0][0][2][0][RTW89_MKK][14] = 64,
+ [0][0][2][0][RTW89_FCC][14] = 70,
+ [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] = 76,
- [0][0][2][0][RTW89_ETSI][15] = 62,
- [0][0][2][0][RTW89_MKK][15] = 78,
- [0][0][2][0][RTW89_IC][15] = 76,
+ [0][0][2][0][RTW89_FCC][15] = 66,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][17] = 62,
- [0][0][2][0][RTW89_MKK][17] = 78,
- [0][0][2][0][RTW89_IC][17] = 80,
+ [0][0][2][0][RTW89_FCC][17] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][19] = 62,
- [0][0][2][0][RTW89_MKK][19] = 78,
- [0][0][2][0][RTW89_IC][19] = 80,
+ [0][0][2][0][RTW89_FCC][19] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][21] = 62,
- [0][0][2][0][RTW89_MKK][21] = 78,
- [0][0][2][0][RTW89_IC][21] = 80,
+ [0][0][2][0][RTW89_FCC][21] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][23] = 62,
- [0][0][2][0][RTW89_MKK][23] = 78,
- [0][0][2][0][RTW89_IC][23] = 80,
+ [0][0][2][0][RTW89_FCC][23] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][25] = 62,
- [0][0][2][0][RTW89_MKK][25] = 78,
+ [0][0][2][0][RTW89_FCC][25] = 70,
+ [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_ACMA][25] = 127,
- [0][0][2][0][RTW89_FCC][27] = 80,
- [0][0][2][0][RTW89_ETSI][27] = 62,
- [0][0][2][0][RTW89_MKK][27] = 78,
+ [0][0][2][0][RTW89_FCC][27] = 70,
+ [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_ACMA][27] = 127,
- [0][0][2][0][RTW89_FCC][29] = 80,
- [0][0][2][0][RTW89_ETSI][29] = 62,
- [0][0][2][0][RTW89_MKK][29] = 78,
+ [0][0][2][0][RTW89_FCC][29] = 70,
+ [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_ACMA][29] = 127,
- [0][0][2][0][RTW89_FCC][31] = 80,
- [0][0][2][0][RTW89_ETSI][31] = 62,
- [0][0][2][0][RTW89_MKK][31] = 78,
- [0][0][2][0][RTW89_IC][31] = 80,
+ [0][0][2][0][RTW89_FCC][31] = 70,
+ [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] = 80,
- [0][0][2][0][RTW89_ETSI][33] = 62,
- [0][0][2][0][RTW89_MKK][33] = 78,
- [0][0][2][0][RTW89_IC][33] = 80,
+ [0][0][2][0][RTW89_FCC][33] = 70,
+ [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] = 72,
- [0][0][2][0][RTW89_ETSI][35] = 62,
- [0][0][2][0][RTW89_MKK][35] = 78,
- [0][0][2][0][RTW89_IC][35] = 72,
+ [0][0][2][0][RTW89_FCC][35] = 62,
+ [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] = 80,
+ [0][0][2][0][RTW89_FCC][37] = 70,
[0][0][2][0][RTW89_ETSI][37] = 127,
- [0][0][2][0][RTW89_MKK][37] = 78,
- [0][0][2][0][RTW89_IC][37] = 80,
- [0][0][2][0][RTW89_ACMA][37] = 78,
- [0][0][2][0][RTW89_FCC][38] = 80,
+ [0][0][2][0][RTW89_MKK][37] = 70,
+ [0][0][2][0][RTW89_IC][37] = 70,
+ [0][0][2][0][RTW89_ACMA][37] = 70,
+ [0][0][2][0][RTW89_FCC][38] = 70,
[0][0][2][0][RTW89_ETSI][38] = 30,
[0][0][2][0][RTW89_MKK][38] = 127,
- [0][0][2][0][RTW89_IC][38] = 80,
- [0][0][2][0][RTW89_ACMA][38] = 78,
- [0][0][2][0][RTW89_FCC][40] = 80,
+ [0][0][2][0][RTW89_IC][38] = 70,
+ [0][0][2][0][RTW89_ACMA][38] = 70,
+ [0][0][2][0][RTW89_FCC][40] = 70,
[0][0][2][0][RTW89_ETSI][40] = 30,
[0][0][2][0][RTW89_MKK][40] = 127,
- [0][0][2][0][RTW89_IC][40] = 80,
- [0][0][2][0][RTW89_ACMA][40] = 78,
- [0][0][2][0][RTW89_FCC][42] = 80,
+ [0][0][2][0][RTW89_IC][40] = 70,
+ [0][0][2][0][RTW89_ACMA][40] = 70,
+ [0][0][2][0][RTW89_FCC][42] = 70,
[0][0][2][0][RTW89_ETSI][42] = 30,
[0][0][2][0][RTW89_MKK][42] = 127,
- [0][0][2][0][RTW89_IC][42] = 80,
- [0][0][2][0][RTW89_ACMA][42] = 78,
- [0][0][2][0][RTW89_FCC][44] = 80,
+ [0][0][2][0][RTW89_IC][42] = 70,
+ [0][0][2][0][RTW89_ACMA][42] = 70,
+ [0][0][2][0][RTW89_FCC][44] = 70,
[0][0][2][0][RTW89_ETSI][44] = 30,
[0][0][2][0][RTW89_MKK][44] = 127,
- [0][0][2][0][RTW89_IC][44] = 80,
- [0][0][2][0][RTW89_ACMA][44] = 78,
- [0][0][2][0][RTW89_FCC][46] = 80,
+ [0][0][2][0][RTW89_IC][44] = 70,
+ [0][0][2][0][RTW89_ACMA][44] = 70,
+ [0][0][2][0][RTW89_FCC][46] = 70,
[0][0][2][0][RTW89_ETSI][46] = 30,
[0][0][2][0][RTW89_MKK][46] = 127,
- [0][0][2][0][RTW89_IC][46] = 80,
- [0][0][2][0][RTW89_ACMA][46] = 78,
- [0][0][2][0][RTW89_FCC][48] = 80,
+ [0][0][2][0][RTW89_IC][46] = 70,
+ [0][0][2][0][RTW89_ACMA][46] = 70,
+ [0][0][2][0][RTW89_FCC][48] = 70,
[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_ACMA][48] = 127,
- [0][0][2][0][RTW89_FCC][50] = 80,
+ [0][0][2][0][RTW89_FCC][50] = 70,
[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_ACMA][50] = 127,
- [0][0][2][0][RTW89_FCC][52] = 80,
+ [0][0][2][0][RTW89_FCC][52] = 70,
[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_ACMA][52] = 127,
- [0][1][2][0][RTW89_FCC][0] = 72,
- [0][1][2][0][RTW89_ETSI][0] = 50,
- [0][1][2][0][RTW89_MKK][0] = 52,
+ [0][1][2][0][RTW89_FCC][0] = 62,
+ [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_FCC][2] = 72,
- [0][1][2][0][RTW89_ETSI][2] = 50,
- [0][1][2][0][RTW89_MKK][2] = 52,
+ [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_FCC][4] = 72,
- [0][1][2][0][RTW89_ETSI][4] = 50,
- [0][1][2][0][RTW89_MKK][4] = 52,
+ [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_FCC][6] = 72,
- [0][1][2][0][RTW89_ETSI][6] = 50,
- [0][1][2][0][RTW89_MKK][6] = 52,
+ [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_FCC][8] = 72,
- [0][1][2][0][RTW89_ETSI][8] = 50,
- [0][1][2][0][RTW89_MKK][8] = 52,
+ [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_FCC][10] = 72,
- [0][1][2][0][RTW89_ETSI][10] = 50,
- [0][1][2][0][RTW89_MKK][10] = 52,
+ [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_FCC][12] = 72,
- [0][1][2][0][RTW89_ETSI][12] = 50,
- [0][1][2][0][RTW89_MKK][12] = 52,
+ [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_FCC][14] = 72,
- [0][1][2][0][RTW89_ETSI][14] = 50,
- [0][1][2][0][RTW89_MKK][14] = 52,
+ [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_FCC][15] = 70,
- [0][1][2][0][RTW89_ETSI][15] = 50,
- [0][1][2][0][RTW89_MKK][15] = 72,
+ [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_FCC][17] = 72,
- [0][1][2][0][RTW89_ETSI][17] = 50,
- [0][1][2][0][RTW89_MKK][17] = 72,
- [0][1][2][0][RTW89_IC][17] = 72,
+ [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_FCC][19] = 72,
- [0][1][2][0][RTW89_ETSI][19] = 50,
- [0][1][2][0][RTW89_MKK][19] = 72,
- [0][1][2][0][RTW89_IC][19] = 72,
+ [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_FCC][21] = 72,
- [0][1][2][0][RTW89_ETSI][21] = 50,
- [0][1][2][0][RTW89_MKK][21] = 72,
- [0][1][2][0][RTW89_IC][21] = 72,
+ [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_FCC][23] = 72,
- [0][1][2][0][RTW89_ETSI][23] = 50,
- [0][1][2][0][RTW89_MKK][23] = 72,
- [0][1][2][0][RTW89_IC][23] = 72,
+ [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_FCC][25] = 72,
- [0][1][2][0][RTW89_ETSI][25] = 50,
- [0][1][2][0][RTW89_MKK][25] = 72,
+ [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_ACMA][25] = 127,
- [0][1][2][0][RTW89_FCC][27] = 72,
- [0][1][2][0][RTW89_ETSI][27] = 50,
- [0][1][2][0][RTW89_MKK][27] = 72,
+ [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_ACMA][27] = 127,
- [0][1][2][0][RTW89_FCC][29] = 72,
- [0][1][2][0][RTW89_ETSI][29] = 50,
- [0][1][2][0][RTW89_MKK][29] = 72,
+ [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_ACMA][29] = 127,
- [0][1][2][0][RTW89_FCC][31] = 72,
- [0][1][2][0][RTW89_ETSI][31] = 50,
- [0][1][2][0][RTW89_MKK][31] = 72,
- [0][1][2][0][RTW89_IC][31] = 72,
+ [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_FCC][33] = 72,
- [0][1][2][0][RTW89_ETSI][33] = 50,
- [0][1][2][0][RTW89_MKK][33] = 72,
- [0][1][2][0][RTW89_IC][33] = 72,
+ [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] = 68,
- [0][1][2][0][RTW89_ETSI][35] = 50,
- [0][1][2][0][RTW89_MKK][35] = 72,
+ [0][1][2][0][RTW89_FCC][35] = 58,
+ [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] = 72,
+ [0][1][2][0][RTW89_FCC][37] = 62,
[0][1][2][0][RTW89_ETSI][37] = 127,
- [0][1][2][0][RTW89_MKK][37] = 72,
- [0][1][2][0][RTW89_IC][37] = 72,
- [0][1][2][0][RTW89_ACMA][37] = 72,
- [0][1][2][0][RTW89_FCC][38] = 80,
+ [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_ETSI][38] = 18,
[0][1][2][0][RTW89_MKK][38] = 127,
- [0][1][2][0][RTW89_IC][38] = 80,
- [0][1][2][0][RTW89_ACMA][38] = 76,
- [0][1][2][0][RTW89_FCC][40] = 80,
+ [0][1][2][0][RTW89_IC][38] = 70,
+ [0][1][2][0][RTW89_ACMA][38] = 70,
+ [0][1][2][0][RTW89_FCC][40] = 70,
[0][1][2][0][RTW89_ETSI][40] = 18,
[0][1][2][0][RTW89_MKK][40] = 127,
- [0][1][2][0][RTW89_IC][40] = 80,
- [0][1][2][0][RTW89_ACMA][40] = 76,
- [0][1][2][0][RTW89_FCC][42] = 80,
+ [0][1][2][0][RTW89_IC][40] = 70,
+ [0][1][2][0][RTW89_ACMA][40] = 70,
+ [0][1][2][0][RTW89_FCC][42] = 70,
[0][1][2][0][RTW89_ETSI][42] = 18,
[0][1][2][0][RTW89_MKK][42] = 127,
- [0][1][2][0][RTW89_IC][42] = 80,
- [0][1][2][0][RTW89_ACMA][42] = 78,
- [0][1][2][0][RTW89_FCC][44] = 80,
+ [0][1][2][0][RTW89_IC][42] = 70,
+ [0][1][2][0][RTW89_ACMA][42] = 70,
+ [0][1][2][0][RTW89_FCC][44] = 70,
[0][1][2][0][RTW89_ETSI][44] = 18,
[0][1][2][0][RTW89_MKK][44] = 127,
- [0][1][2][0][RTW89_IC][44] = 80,
- [0][1][2][0][RTW89_ACMA][44] = 78,
- [0][1][2][0][RTW89_FCC][46] = 80,
+ [0][1][2][0][RTW89_IC][44] = 70,
+ [0][1][2][0][RTW89_ACMA][44] = 70,
+ [0][1][2][0][RTW89_FCC][46] = 70,
[0][1][2][0][RTW89_ETSI][46] = 18,
[0][1][2][0][RTW89_MKK][46] = 127,
- [0][1][2][0][RTW89_IC][46] = 80,
- [0][1][2][0][RTW89_ACMA][46] = 78,
- [0][1][2][0][RTW89_FCC][48] = 60,
+ [0][1][2][0][RTW89_IC][46] = 70,
+ [0][1][2][0][RTW89_ACMA][46] = 70,
+ [0][1][2][0][RTW89_FCC][48] = 50,
[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_ACMA][48] = 127,
- [0][1][2][0][RTW89_FCC][50] = 60,
+ [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_ACMA][50] = 127,
- [0][1][2][0][RTW89_FCC][52] = 60,
+ [0][1][2][0][RTW89_FCC][52] = 50,
[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_ACMA][52] = 127,
- [0][1][2][1][RTW89_FCC][0] = 70,
- [0][1][2][1][RTW89_ETSI][0] = 42,
- [0][1][2][1][RTW89_MKK][0] = 52,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][2] = 42,
- [0][1][2][1][RTW89_MKK][2] = 52,
+ [0][1][2][1][RTW89_FCC][2] = 60,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][4] = 42,
- [0][1][2][1][RTW89_MKK][4] = 52,
+ [0][1][2][1][RTW89_FCC][4] = 60,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][6] = 42,
- [0][1][2][1][RTW89_MKK][6] = 52,
+ [0][1][2][1][RTW89_FCC][6] = 60,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][8] = 42,
- [0][1][2][1][RTW89_MKK][8] = 52,
+ [0][1][2][1][RTW89_FCC][8] = 60,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][10] = 42,
- [0][1][2][1][RTW89_MKK][10] = 52,
+ [0][1][2][1][RTW89_FCC][10] = 60,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][12] = 42,
- [0][1][2][1][RTW89_MKK][12] = 52,
+ [0][1][2][1][RTW89_FCC][12] = 60,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][14] = 42,
- [0][1][2][1][RTW89_MKK][14] = 52,
+ [0][1][2][1][RTW89_FCC][14] = 60,
+ [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_FCC][15] = 70,
- [0][1][2][1][RTW89_ETSI][15] = 42,
- [0][1][2][1][RTW89_MKK][15] = 72,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][17] = 42,
- [0][1][2][1][RTW89_MKK][17] = 72,
+ [0][1][2][1][RTW89_FCC][17] = 60,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][19] = 42,
- [0][1][2][1][RTW89_MKK][19] = 72,
+ [0][1][2][1][RTW89_FCC][19] = 60,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][21] = 42,
- [0][1][2][1][RTW89_MKK][21] = 72,
+ [0][1][2][1][RTW89_FCC][21] = 60,
+ [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] = 70,
- [0][1][2][1][RTW89_ETSI][23] = 42,
- [0][1][2][1][RTW89_MKK][23] = 72,
+ [0][1][2][1][RTW89_FCC][23] = 60,
+ [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] = 68,
- [0][1][2][1][RTW89_ETSI][25] = 42,
- [0][1][2][1][RTW89_MKK][25] = 72,
+ [0][1][2][1][RTW89_FCC][25] = 58,
+ [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_ACMA][25] = 127,
- [0][1][2][1][RTW89_FCC][27] = 68,
- [0][1][2][1][RTW89_ETSI][27] = 42,
- [0][1][2][1][RTW89_MKK][27] = 72,
+ [0][1][2][1][RTW89_FCC][27] = 58,
+ [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_ACMA][27] = 127,
- [0][1][2][1][RTW89_FCC][29] = 68,
- [0][1][2][1][RTW89_ETSI][29] = 42,
- [0][1][2][1][RTW89_MKK][29] = 72,
+ [0][1][2][1][RTW89_FCC][29] = 58,
+ [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_ACMA][29] = 127,
- [0][1][2][1][RTW89_FCC][31] = 68,
- [0][1][2][1][RTW89_ETSI][31] = 42,
- [0][1][2][1][RTW89_MKK][31] = 72,
+ [0][1][2][1][RTW89_FCC][31] = 58,
+ [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] = 68,
- [0][1][2][1][RTW89_ETSI][33] = 42,
- [0][1][2][1][RTW89_MKK][33] = 72,
+ [0][1][2][1][RTW89_FCC][33] = 58,
+ [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] = 68,
- [0][1][2][1][RTW89_ETSI][35] = 42,
- [0][1][2][1][RTW89_MKK][35] = 72,
+ [0][1][2][1][RTW89_FCC][35] = 58,
+ [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] = 70,
+ [0][1][2][1][RTW89_FCC][37] = 60,
[0][1][2][1][RTW89_ETSI][37] = 127,
- [0][1][2][1][RTW89_MKK][37] = 72,
+ [0][1][2][1][RTW89_MKK][37] = 68,
[0][1][2][1][RTW89_IC][37] = 70,
- [0][1][2][1][RTW89_ACMA][37] = 72,
- [0][1][2][1][RTW89_FCC][38] = 80,
- [0][1][2][1][RTW89_ETSI][38] = 8,
+ [0][1][2][1][RTW89_ACMA][37] = 70,
+ [0][1][2][1][RTW89_FCC][38] = 70,
+ [0][1][2][1][RTW89_ETSI][38] = 6,
[0][1][2][1][RTW89_MKK][38] = 127,
- [0][1][2][1][RTW89_IC][38] = 80,
- [0][1][2][1][RTW89_ACMA][38] = 76,
- [0][1][2][1][RTW89_FCC][40] = 80,
- [0][1][2][1][RTW89_ETSI][40] = 8,
+ [0][1][2][1][RTW89_IC][38] = 70,
+ [0][1][2][1][RTW89_ACMA][38] = 70,
+ [0][1][2][1][RTW89_FCC][40] = 70,
+ [0][1][2][1][RTW89_ETSI][40] = 6,
[0][1][2][1][RTW89_MKK][40] = 127,
- [0][1][2][1][RTW89_IC][40] = 80,
- [0][1][2][1][RTW89_ACMA][40] = 76,
- [0][1][2][1][RTW89_FCC][42] = 80,
- [0][1][2][1][RTW89_ETSI][42] = 8,
+ [0][1][2][1][RTW89_IC][40] = 70,
+ [0][1][2][1][RTW89_ACMA][40] = 70,
+ [0][1][2][1][RTW89_FCC][42] = 70,
+ [0][1][2][1][RTW89_ETSI][42] = 6,
[0][1][2][1][RTW89_MKK][42] = 127,
- [0][1][2][1][RTW89_IC][42] = 80,
- [0][1][2][1][RTW89_ACMA][42] = 78,
- [0][1][2][1][RTW89_FCC][44] = 80,
- [0][1][2][1][RTW89_ETSI][44] = 8,
+ [0][1][2][1][RTW89_IC][42] = 70,
+ [0][1][2][1][RTW89_ACMA][42] = 70,
+ [0][1][2][1][RTW89_FCC][44] = 70,
+ [0][1][2][1][RTW89_ETSI][44] = 6,
[0][1][2][1][RTW89_MKK][44] = 127,
- [0][1][2][1][RTW89_IC][44] = 80,
- [0][1][2][1][RTW89_ACMA][44] = 78,
- [0][1][2][1][RTW89_FCC][46] = 80,
- [0][1][2][1][RTW89_ETSI][46] = 8,
+ [0][1][2][1][RTW89_IC][44] = 70,
+ [0][1][2][1][RTW89_ACMA][44] = 70,
+ [0][1][2][1][RTW89_FCC][46] = 70,
+ [0][1][2][1][RTW89_ETSI][46] = 6,
[0][1][2][1][RTW89_MKK][46] = 127,
- [0][1][2][1][RTW89_IC][46] = 80,
- [0][1][2][1][RTW89_ACMA][46] = 78,
- [0][1][2][1][RTW89_FCC][48] = 60,
+ [0][1][2][1][RTW89_IC][46] = 70,
+ [0][1][2][1][RTW89_ACMA][46] = 70,
+ [0][1][2][1][RTW89_FCC][48] = 50,
[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_ACMA][48] = 127,
- [0][1][2][1][RTW89_FCC][50] = 60,
+ [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_ACMA][50] = 127,
- [0][1][2][1][RTW89_FCC][52] = 60,
+ [0][1][2][1][RTW89_FCC][52] = 50,
[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_ACMA][52] = 127,
- [1][0][2][0][RTW89_FCC][1] = 68,
+ [1][0][2][0][RTW89_FCC][1] = 58,
[1][0][2][0][RTW89_ETSI][1] = 66,
- [1][0][2][0][RTW89_MKK][1] = 72,
- [1][0][2][0][RTW89_IC][1] = 72,
- [1][0][2][0][RTW89_ACMA][1] = 72,
- [1][0][2][0][RTW89_FCC][5] = 80,
+ [1][0][2][0][RTW89_MKK][1] = 66,
+ [1][0][2][0][RTW89_IC][1] = 66,
+ [1][0][2][0][RTW89_ACMA][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] = 72,
- [1][0][2][0][RTW89_IC][5] = 72,
- [1][0][2][0][RTW89_ACMA][5] = 72,
- [1][0][2][0][RTW89_FCC][9] = 80,
+ [1][0][2][0][RTW89_MKK][5] = 66,
+ [1][0][2][0][RTW89_IC][5] = 66,
+ [1][0][2][0][RTW89_ACMA][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] = 72,
- [1][0][2][0][RTW89_IC][9] = 72,
- [1][0][2][0][RTW89_ACMA][9] = 72,
- [1][0][2][0][RTW89_FCC][13] = 68,
+ [1][0][2][0][RTW89_MKK][9] = 66,
+ [1][0][2][0][RTW89_IC][9] = 66,
+ [1][0][2][0][RTW89_ACMA][9] = 66,
+ [1][0][2][0][RTW89_FCC][13] = 58,
[1][0][2][0][RTW89_ETSI][13] = 66,
- [1][0][2][0][RTW89_MKK][13] = 72,
- [1][0][2][0][RTW89_IC][13] = 72,
- [1][0][2][0][RTW89_ACMA][13] = 72,
- [1][0][2][0][RTW89_FCC][16] = 66,
+ [1][0][2][0][RTW89_MKK][13] = 66,
+ [1][0][2][0][RTW89_IC][13] = 66,
+ [1][0][2][0][RTW89_ACMA][13] = 66,
+ [1][0][2][0][RTW89_FCC][16] = 56,
[1][0][2][0][RTW89_ETSI][16] = 66,
- [1][0][2][0][RTW89_MKK][16] = 76,
- [1][0][2][0][RTW89_IC][16] = 72,
- [1][0][2][0][RTW89_ACMA][16] = 72,
- [1][0][2][0][RTW89_FCC][20] = 80,
+ [1][0][2][0][RTW89_MKK][16] = 66,
+ [1][0][2][0][RTW89_IC][16] = 66,
+ [1][0][2][0][RTW89_ACMA][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] = 76,
- [1][0][2][0][RTW89_IC][20] = 80,
- [1][0][2][0][RTW89_ACMA][20] = 72,
- [1][0][2][0][RTW89_FCC][24] = 80,
+ [1][0][2][0][RTW89_MKK][20] = 66,
+ [1][0][2][0][RTW89_IC][20] = 66,
+ [1][0][2][0][RTW89_ACMA][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] = 76,
+ [1][0][2][0][RTW89_MKK][24] = 66,
[1][0][2][0][RTW89_IC][24] = 127,
[1][0][2][0][RTW89_ACMA][24] = 127,
- [1][0][2][0][RTW89_FCC][28] = 80,
+ [1][0][2][0][RTW89_FCC][28] = 68,
[1][0][2][0][RTW89_ETSI][28] = 66,
- [1][0][2][0][RTW89_MKK][28] = 76,
+ [1][0][2][0][RTW89_MKK][28] = 66,
[1][0][2][0][RTW89_IC][28] = 127,
[1][0][2][0][RTW89_ACMA][28] = 127,
- [1][0][2][0][RTW89_FCC][32] = 78,
+ [1][0][2][0][RTW89_FCC][32] = 68,
[1][0][2][0][RTW89_ETSI][32] = 66,
- [1][0][2][0][RTW89_MKK][32] = 76,
- [1][0][2][0][RTW89_IC][32] = 78,
+ [1][0][2][0][RTW89_MKK][32] = 66,
+ [1][0][2][0][RTW89_IC][32] = 66,
[1][0][2][0][RTW89_ACMA][32] = 66,
- [1][0][2][0][RTW89_FCC][36] = 80,
+ [1][0][2][0][RTW89_FCC][36] = 68,
[1][0][2][0][RTW89_ETSI][36] = 127,
- [1][0][2][0][RTW89_MKK][36] = 76,
- [1][0][2][0][RTW89_IC][36] = 80,
- [1][0][2][0][RTW89_ACMA][36] = 76,
- [1][0][2][0][RTW89_FCC][39] = 80,
+ [1][0][2][0][RTW89_MKK][36] = 66,
+ [1][0][2][0][RTW89_IC][36] = 66,
+ [1][0][2][0][RTW89_ACMA][36] = 66,
+ [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] = 80,
- [1][0][2][0][RTW89_ACMA][39] = 76,
- [1][0][2][0][RTW89_FCC][43] = 80,
+ [1][0][2][0][RTW89_IC][39] = 66,
+ [1][0][2][0][RTW89_ACMA][39] = 66,
+ [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] = 80,
- [1][0][2][0][RTW89_ACMA][43] = 76,
- [1][0][2][0][RTW89_FCC][47] = 80,
+ [1][0][2][0][RTW89_IC][43] = 66,
+ [1][0][2][0][RTW89_ACMA][43] = 66,
+ [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_ACMA][47] = 127,
- [1][0][2][0][RTW89_FCC][51] = 72,
+ [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_ACMA][51] = 127,
- [1][1][2][0][RTW89_FCC][1] = 64,
+ [1][1][2][0][RTW89_FCC][1] = 54,
[1][1][2][0][RTW89_ETSI][1] = 54,
- [1][1][2][0][RTW89_MKK][1] = 60,
+ [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_FCC][5] = 78,
+ [1][1][2][0][RTW89_FCC][5] = 68,
[1][1][2][0][RTW89_ETSI][5] = 54,
- [1][1][2][0][RTW89_MKK][5] = 60,
+ [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_FCC][9] = 78,
+ [1][1][2][0][RTW89_FCC][9] = 68,
[1][1][2][0][RTW89_ETSI][9] = 54,
- [1][1][2][0][RTW89_MKK][9] = 60,
+ [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_FCC][13] = 64,
+ [1][1][2][0][RTW89_FCC][13] = 54,
[1][1][2][0][RTW89_ETSI][13] = 54,
- [1][1][2][0][RTW89_MKK][13] = 60,
+ [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] = 58,
+ [1][1][2][0][RTW89_FCC][16] = 48,
[1][1][2][0][RTW89_ETSI][16] = 54,
- [1][1][2][0][RTW89_MKK][16] = 72,
+ [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_FCC][20] = 78,
+ [1][1][2][0][RTW89_FCC][20] = 68,
[1][1][2][0][RTW89_ETSI][20] = 54,
- [1][1][2][0][RTW89_MKK][20] = 72,
- [1][1][2][0][RTW89_IC][20] = 78,
+ [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_FCC][24] = 78,
+ [1][1][2][0][RTW89_FCC][24] = 68,
[1][1][2][0][RTW89_ETSI][24] = 54,
- [1][1][2][0][RTW89_MKK][24] = 72,
+ [1][1][2][0][RTW89_MKK][24] = 66,
[1][1][2][0][RTW89_IC][24] = 127,
[1][1][2][0][RTW89_ACMA][24] = 127,
- [1][1][2][0][RTW89_FCC][28] = 78,
+ [1][1][2][0][RTW89_FCC][28] = 68,
[1][1][2][0][RTW89_ETSI][28] = 54,
- [1][1][2][0][RTW89_MKK][28] = 72,
+ [1][1][2][0][RTW89_MKK][28] = 66,
[1][1][2][0][RTW89_IC][28] = 127,
[1][1][2][0][RTW89_ACMA][28] = 127,
- [1][1][2][0][RTW89_FCC][32] = 70,
+ [1][1][2][0][RTW89_FCC][32] = 60,
[1][1][2][0][RTW89_ETSI][32] = 54,
- [1][1][2][0][RTW89_MKK][32] = 72,
- [1][1][2][0][RTW89_IC][32] = 70,
+ [1][1][2][0][RTW89_MKK][32] = 66,
+ [1][1][2][0][RTW89_IC][32] = 66,
[1][1][2][0][RTW89_ACMA][32] = 54,
- [1][1][2][0][RTW89_FCC][36] = 78,
+ [1][1][2][0][RTW89_FCC][36] = 68,
[1][1][2][0][RTW89_ETSI][36] = 127,
- [1][1][2][0][RTW89_MKK][36] = 72,
- [1][1][2][0][RTW89_IC][36] = 78,
- [1][1][2][0][RTW89_ACMA][36] = 76,
- [1][1][2][0][RTW89_FCC][39] = 80,
+ [1][1][2][0][RTW89_MKK][36] = 66,
+ [1][1][2][0][RTW89_IC][36] = 66,
+ [1][1][2][0][RTW89_ACMA][36] = 66,
+ [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] = 80,
- [1][1][2][0][RTW89_ACMA][39] = 74,
- [1][1][2][0][RTW89_FCC][43] = 80,
+ [1][1][2][0][RTW89_IC][39] = 66,
+ [1][1][2][0][RTW89_ACMA][39] = 66,
+ [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] = 80,
- [1][1][2][0][RTW89_ACMA][43] = 76,
- [1][1][2][0][RTW89_FCC][47] = 70,
+ [1][1][2][0][RTW89_IC][43] = 66,
+ [1][1][2][0][RTW89_ACMA][43] = 66,
+ [1][1][2][0][RTW89_FCC][47] = 60,
[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_ACMA][47] = 127,
- [1][1][2][0][RTW89_FCC][51] = 68,
+ [1][1][2][0][RTW89_FCC][51] = 58,
[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_ACMA][51] = 127,
- [1][1][2][1][RTW89_FCC][1] = 64,
- [1][1][2][1][RTW89_ETSI][1] = 42,
- [1][1][2][1][RTW89_MKK][1] = 60,
+ [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] = 70,
- [1][1][2][1][RTW89_ETSI][5] = 42,
- [1][1][2][1][RTW89_MKK][5] = 60,
+ [1][1][2][1][RTW89_FCC][5] = 60,
+ [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] = 70,
- [1][1][2][1][RTW89_ETSI][9] = 42,
- [1][1][2][1][RTW89_MKK][9] = 60,
+ [1][1][2][1][RTW89_FCC][9] = 60,
+ [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_FCC][13] = 64,
- [1][1][2][1][RTW89_ETSI][13] = 42,
- [1][1][2][1][RTW89_MKK][13] = 60,
+ [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] = 58,
- [1][1][2][1][RTW89_ETSI][16] = 42,
- [1][1][2][1][RTW89_MKK][16] = 72,
+ [1][1][2][1][RTW89_FCC][16] = 48,
+ [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] = 70,
- [1][1][2][1][RTW89_ETSI][20] = 42,
- [1][1][2][1][RTW89_MKK][20] = 72,
- [1][1][2][1][RTW89_IC][20] = 70,
+ [1][1][2][1][RTW89_FCC][20] = 60,
+ [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] = 70,
- [1][1][2][1][RTW89_ETSI][24] = 42,
- [1][1][2][1][RTW89_MKK][24] = 72,
+ [1][1][2][1][RTW89_FCC][24] = 60,
+ [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_ACMA][24] = 127,
- [1][1][2][1][RTW89_FCC][28] = 70,
- [1][1][2][1][RTW89_ETSI][28] = 42,
- [1][1][2][1][RTW89_MKK][28] = 72,
+ [1][1][2][1][RTW89_FCC][28] = 60,
+ [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_ACMA][28] = 127,
- [1][1][2][1][RTW89_FCC][32] = 70,
- [1][1][2][1][RTW89_ETSI][32] = 42,
- [1][1][2][1][RTW89_MKK][32] = 72,
- [1][1][2][1][RTW89_IC][32] = 70,
+ [1][1][2][1][RTW89_FCC][32] = 60,
+ [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] = 70,
+ [1][1][2][1][RTW89_FCC][36] = 60,
[1][1][2][1][RTW89_ETSI][36] = 127,
- [1][1][2][1][RTW89_MKK][36] = 72,
- [1][1][2][1][RTW89_IC][36] = 70,
- [1][1][2][1][RTW89_ACMA][36] = 72,
- [1][1][2][1][RTW89_FCC][39] = 80,
- [1][1][2][1][RTW89_ETSI][39] = 8,
+ [1][1][2][1][RTW89_MKK][36] = 66,
+ [1][1][2][1][RTW89_IC][36] = 66,
+ [1][1][2][1][RTW89_ACMA][36] = 66,
+ [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] = 80,
- [1][1][2][1][RTW89_ACMA][39] = 74,
- [1][1][2][1][RTW89_FCC][43] = 80,
- [1][1][2][1][RTW89_ETSI][43] = 8,
+ [1][1][2][1][RTW89_IC][39] = 66,
+ [1][1][2][1][RTW89_ACMA][39] = 66,
+ [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] = 80,
- [1][1][2][1][RTW89_ACMA][43] = 76,
- [1][1][2][1][RTW89_FCC][47] = 70,
+ [1][1][2][1][RTW89_IC][43] = 66,
+ [1][1][2][1][RTW89_ACMA][43] = 66,
+ [1][1][2][1][RTW89_FCC][47] = 60,
[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_ACMA][47] = 127,
- [1][1][2][1][RTW89_FCC][51] = 68,
+ [1][1][2][1][RTW89_FCC][51] = 58,
[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_ACMA][51] = 127,
- [2][0][2][0][RTW89_FCC][3] = 66,
- [2][0][2][0][RTW89_ETSI][3] = 66,
- [2][0][2][0][RTW89_MKK][3] = 66,
- [2][0][2][0][RTW89_IC][3] = 64,
- [2][0][2][0][RTW89_ACMA][3] = 66,
- [2][0][2][0][RTW89_FCC][11] = 68,
- [2][0][2][0][RTW89_ETSI][11] = 66,
- [2][0][2][0][RTW89_MKK][11] = 66,
- [2][0][2][0][RTW89_IC][11] = 66,
- [2][0][2][0][RTW89_ACMA][11] = 66,
- [2][0][2][0][RTW89_FCC][18] = 64,
- [2][0][2][0][RTW89_ETSI][18] = 66,
- [2][0][2][0][RTW89_MKK][18] = 72,
- [2][0][2][0][RTW89_IC][18] = 64,
- [2][0][2][0][RTW89_ACMA][18] = 66,
- [2][0][2][0][RTW89_FCC][26] = 76,
- [2][0][2][0][RTW89_ETSI][26] = 66,
- [2][0][2][0][RTW89_MKK][26] = 72,
+ [2][0][2][0][RTW89_FCC][3] = 56,
+ [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_ACMA][3] = 60,
+ [2][0][2][0][RTW89_FCC][11] = 58,
+ [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_ACMA][11] = 60,
+ [2][0][2][0][RTW89_FCC][18] = 54,
+ [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_ACMA][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_ACMA][26] = 127,
- [2][0][2][0][RTW89_FCC][34] = 76,
+ [2][0][2][0][RTW89_FCC][34] = 62,
[2][0][2][0][RTW89_ETSI][34] = 127,
- [2][0][2][0][RTW89_MKK][34] = 72,
- [2][0][2][0][RTW89_IC][34] = 76,
- [2][0][2][0][RTW89_ACMA][34] = 72,
- [2][0][2][0][RTW89_FCC][41] = 76,
+ [2][0][2][0][RTW89_MKK][34] = 60,
+ [2][0][2][0][RTW89_IC][34] = 60,
+ [2][0][2][0][RTW89_ACMA][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] = 76,
- [2][0][2][0][RTW89_ACMA][41] = 72,
- [2][0][2][0][RTW89_FCC][49] = 66,
+ [2][0][2][0][RTW89_IC][41] = 60,
+ [2][0][2][0][RTW89_ACMA][41] = 60,
+ [2][0][2][0][RTW89_FCC][49] = 56,
[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_ACMA][49] = 127,
- [2][1][2][0][RTW89_FCC][3] = 58,
+ [2][1][2][0][RTW89_FCC][3] = 48,
[2][1][2][0][RTW89_ETSI][3] = 54,
- [2][1][2][0][RTW89_MKK][3] = 54,
- [2][1][2][0][RTW89_IC][3] = 54,
- [2][1][2][0][RTW89_ACMA][3] = 54,
- [2][1][2][0][RTW89_FCC][11] = 64,
+ [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_ETSI][11] = 54,
[2][1][2][0][RTW89_MKK][11] = 54,
- [2][1][2][0][RTW89_IC][11] = 54,
- [2][1][2][0][RTW89_ACMA][11] = 54,
- [2][1][2][0][RTW89_FCC][18] = 58,
+ [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_ETSI][18] = 54,
- [2][1][2][0][RTW89_MKK][18] = 72,
+ [2][1][2][0][RTW89_MKK][18] = 60,
[2][1][2][0][RTW89_IC][18] = 58,
- [2][1][2][0][RTW89_ACMA][18] = 54,
- [2][1][2][0][RTW89_FCC][26] = 72,
+ [2][1][2][0][RTW89_ACMA][18] = 52,
+ [2][1][2][0][RTW89_FCC][26] = 62,
[2][1][2][0][RTW89_ETSI][26] = 54,
- [2][1][2][0][RTW89_MKK][26] = 72,
+ [2][1][2][0][RTW89_MKK][26] = 56,
[2][1][2][0][RTW89_IC][26] = 127,
[2][1][2][0][RTW89_ACMA][26] = 127,
- [2][1][2][0][RTW89_FCC][34] = 76,
+ [2][1][2][0][RTW89_FCC][34] = 62,
[2][1][2][0][RTW89_ETSI][34] = 127,
- [2][1][2][0][RTW89_MKK][34] = 72,
- [2][1][2][0][RTW89_IC][34] = 76,
- [2][1][2][0][RTW89_ACMA][34] = 72,
- [2][1][2][0][RTW89_FCC][41] = 76,
+ [2][1][2][0][RTW89_MKK][34] = 60,
+ [2][1][2][0][RTW89_IC][34] = 60,
+ [2][1][2][0][RTW89_ACMA][34] = 60,
+ [2][1][2][0][RTW89_FCC][41] = 62,
[2][1][2][0][RTW89_ETSI][41] = 18,
[2][1][2][0][RTW89_MKK][41] = 127,
- [2][1][2][0][RTW89_IC][41] = 76,
- [2][1][2][0][RTW89_ACMA][41] = 72,
- [2][1][2][0][RTW89_FCC][49] = 60,
+ [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_ETSI][49] = 127,
[2][1][2][0][RTW89_MKK][49] = 127,
[2][1][2][0][RTW89_IC][49] = 127,
[2][1][2][0][RTW89_ACMA][49] = 127,
- [2][1][2][1][RTW89_FCC][3] = 58,
- [2][1][2][1][RTW89_ETSI][3] = 42,
- [2][1][2][1][RTW89_MKK][3] = 54,
- [2][1][2][1][RTW89_IC][3] = 42,
- [2][1][2][1][RTW89_ACMA][3] = 42,
- [2][1][2][1][RTW89_FCC][11] = 64,
- [2][1][2][1][RTW89_ETSI][11] = 42,
+ [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_ACMA][3] = 40,
+ [2][1][2][1][RTW89_FCC][11] = 54,
+ [2][1][2][1][RTW89_ETSI][11] = 40,
[2][1][2][1][RTW89_MKK][11] = 54,
- [2][1][2][1][RTW89_IC][11] = 42,
- [2][1][2][1][RTW89_ACMA][11] = 42,
- [2][1][2][1][RTW89_FCC][18] = 58,
- [2][1][2][1][RTW89_ETSI][18] = 42,
- [2][1][2][1][RTW89_MKK][18] = 72,
+ [2][1][2][1][RTW89_IC][11] = 40,
+ [2][1][2][1][RTW89_ACMA][11] = 40,
+ [2][1][2][1][RTW89_FCC][18] = 48,
+ [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_ACMA][18] = 42,
- [2][1][2][1][RTW89_FCC][26] = 70,
- [2][1][2][1][RTW89_ETSI][26] = 44,
- [2][1][2][1][RTW89_MKK][26] = 72,
+ [2][1][2][1][RTW89_ACMA][18] = 40,
+ [2][1][2][1][RTW89_FCC][26] = 60,
+ [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_ACMA][26] = 127,
- [2][1][2][1][RTW89_FCC][34] = 70,
+ [2][1][2][1][RTW89_FCC][34] = 60,
[2][1][2][1][RTW89_ETSI][34] = 127,
- [2][1][2][1][RTW89_MKK][34] = 72,
- [2][1][2][1][RTW89_IC][34] = 70,
- [2][1][2][1][RTW89_ACMA][34] = 72,
- [2][1][2][1][RTW89_FCC][41] = 76,
- [2][1][2][1][RTW89_ETSI][41] = 8,
+ [2][1][2][1][RTW89_MKK][34] = 60,
+ [2][1][2][1][RTW89_IC][34] = 60,
+ [2][1][2][1][RTW89_ACMA][34] = 60,
+ [2][1][2][1][RTW89_FCC][41] = 62,
+ [2][1][2][1][RTW89_ETSI][41] = 6,
[2][1][2][1][RTW89_MKK][41] = 127,
- [2][1][2][1][RTW89_IC][41] = 76,
- [2][1][2][1][RTW89_ACMA][41] = 72,
- [2][1][2][1][RTW89_FCC][49] = 60,
+ [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_ETSI][49] = 127,
[2][1][2][1][RTW89_MKK][49] = 127,
[2][1][2][1][RTW89_IC][49] = 127,
[2][1][2][1][RTW89_ACMA][49] = 127,
- [3][0][2][0][RTW89_FCC][7] = 56,
- [3][0][2][0][RTW89_ETSI][7] = 56,
- [3][0][2][0][RTW89_MKK][7] = 56,
- [3][0][2][0][RTW89_IC][7] = 56,
- [3][0][2][0][RTW89_ACMA][7] = 56,
- [3][0][2][0][RTW89_FCC][22] = 56,
- [3][0][2][0][RTW89_ETSI][22] = 56,
- [3][0][2][0][RTW89_MKK][22] = 56,
- [3][0][2][0][RTW89_IC][22] = 56,
- [3][0][2][0][RTW89_ACMA][22] = 56,
- [3][0][2][0][RTW89_FCC][45] = 56,
+ [3][0][2][0][RTW89_FCC][7] = 38,
+ [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_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_ETSI][45] = 127,
[3][0][2][0][RTW89_MKK][45] = 127,
[3][0][2][0][RTW89_IC][45] = 127,
[3][0][2][0][RTW89_ACMA][45] = 127,
- [3][1][2][0][RTW89_FCC][7] = 44,
- [3][1][2][0][RTW89_ETSI][7] = 44,
- [3][1][2][0][RTW89_MKK][7] = 44,
+ [3][1][2][0][RTW89_FCC][7] = 26,
+ [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] = 44,
- [3][1][2][0][RTW89_ETSI][22] = 44,
- [3][1][2][0][RTW89_MKK][22] = 44,
+ [3][1][2][0][RTW89_FCC][22] = 42,
+ [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] = 44,
+ [3][1][2][0][RTW89_FCC][45] = 127,
[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_ACMA][45] = 127,
- [3][1][2][1][RTW89_FCC][7] = 32,
- [3][1][2][1][RTW89_ETSI][7] = 32,
- [3][1][2][1][RTW89_MKK][7] = 32,
+ [3][1][2][1][RTW89_FCC][7] = 14,
+ [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] = 32,
- [3][1][2][1][RTW89_ETSI][22] = 32,
- [3][1][2][1][RTW89_MKK][22] = 32,
+ [3][1][2][1][RTW89_FCC][22] = 30,
+ [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] = 32,
+ [3][1][2][1][RTW89_FCC][45] = 127,
[3][1][2][1][RTW89_ETSI][45] = 127,
[3][1][2][1][RTW89_MKK][45] = 127,
[3][1][2][1][RTW89_IC][45] = 127,
@@ -17127,7 +17127,7 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_WW][9] = 32,
[0][0][RTW89_WW][10] = 32,
[0][0][RTW89_WW][11] = 32,
- [0][0][RTW89_WW][12] = 32,
+ [0][0][RTW89_WW][12] = 24,
[0][0][RTW89_WW][13] = 0,
[0][1][RTW89_WW][0] = 20,
[0][1][RTW89_WW][1] = 22,
@@ -17154,8 +17154,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] = 44,
- [1][0][RTW89_WW][12] = 38,
+ [1][0][RTW89_WW][11] = 42,
+ [1][0][RTW89_WW][12] = 30,
[1][0][RTW89_WW][13] = 0,
[1][1][RTW89_WW][0] = 32,
[1][1][RTW89_WW][1] = 32,
@@ -17168,8 +17168,8 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_WW][8] = 32,
[1][1][RTW89_WW][9] = 32,
[1][1][RTW89_WW][10] = 32,
- [1][1][RTW89_WW][11] = 32,
- [1][1][RTW89_WW][12] = 32,
+ [1][1][RTW89_WW][11] = 30,
+ [1][1][RTW89_WW][12] = 24,
[1][1][RTW89_WW][13] = 0,
[2][0][RTW89_WW][0] = 56,
[2][0][RTW89_WW][1] = 56,
@@ -17182,8 +17182,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] = 56,
- [2][0][RTW89_WW][12] = 56,
+ [2][0][RTW89_WW][11] = 42,
+ [2][0][RTW89_WW][12] = 38,
[2][0][RTW89_WW][13] = 0,
[2][1][RTW89_WW][0] = 44,
[2][1][RTW89_WW][1] = 44,
@@ -17196,72 +17196,72 @@ 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] = 44,
- [2][1][RTW89_WW][12] = 42,
+ [2][1][RTW89_WW][11] = 30,
+ [2][1][RTW89_WW][12] = 26,
[2][1][RTW89_WW][13] = 0,
- [0][0][RTW89_FCC][0] = 68,
- [0][0][RTW89_ETSI][0] = 36,
- [0][0][RTW89_MKK][0] = 38,
+ [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_FCC][1] = 68,
- [0][0][RTW89_ETSI][1] = 40,
- [0][0][RTW89_MKK][1] = 44,
+ [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_FCC][2] = 72,
- [0][0][RTW89_ETSI][2] = 40,
- [0][0][RTW89_MKK][2] = 44,
+ [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_FCC][3] = 76,
- [0][0][RTW89_ETSI][3] = 40,
- [0][0][RTW89_MKK][3] = 44,
+ [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_FCC][4] = 76,
- [0][0][RTW89_ETSI][4] = 40,
- [0][0][RTW89_MKK][4] = 44,
+ [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] = 84,
- [0][0][RTW89_ETSI][5] = 40,
- [0][0][RTW89_MKK][5] = 44,
+ [0][0][RTW89_FCC][5] = 76,
+ [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] = 74,
- [0][0][RTW89_ETSI][6] = 40,
- [0][0][RTW89_MKK][6] = 44,
+ [0][0][RTW89_FCC][6] = 66,
+ [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] = 74,
- [0][0][RTW89_ETSI][7] = 40,
- [0][0][RTW89_MKK][7] = 44,
+ [0][0][RTW89_FCC][7] = 66,
+ [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] = 70,
- [0][0][RTW89_ETSI][8] = 40,
- [0][0][RTW89_MKK][8] = 44,
+ [0][0][RTW89_FCC][8] = 62,
+ [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] = 66,
- [0][0][RTW89_ETSI][9] = 40,
- [0][0][RTW89_MKK][9] = 44,
+ [0][0][RTW89_FCC][9] = 58,
+ [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] = 66,
- [0][0][RTW89_ETSI][10] = 40,
- [0][0][RTW89_MKK][10] = 44,
+ [0][0][RTW89_FCC][10] = 58,
+ [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] = 56,
- [0][0][RTW89_ETSI][11] = 40,
- [0][0][RTW89_MKK][11] = 44,
+ [0][0][RTW89_FCC][11] = 42,
+ [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] = 32,
- [0][0][RTW89_ETSI][12] = 36,
- [0][0][RTW89_MKK][12] = 38,
+ [0][0][RTW89_FCC][12] = 24,
+ [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_FCC][13] = 127,
@@ -17269,69 +17269,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_MKK][13] = 127,
[0][0][RTW89_IC][13] = 127,
[0][0][RTW89_ACMA][13] = 127,
- [0][1][RTW89_FCC][0] = 62,
- [0][1][RTW89_ETSI][0] = 24,
- [0][1][RTW89_MKK][0] = 26,
+ [0][1][RTW89_FCC][0] = 46,
+ [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] = 62,
- [0][1][RTW89_ETSI][1] = 26,
- [0][1][RTW89_MKK][1] = 32,
+ [0][1][RTW89_FCC][1] = 46,
+ [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] = 66,
- [0][1][RTW89_ETSI][2] = 26,
- [0][1][RTW89_MKK][2] = 32,
+ [0][1][RTW89_FCC][2] = 50,
+ [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] = 70,
- [0][1][RTW89_ETSI][3] = 26,
- [0][1][RTW89_MKK][3] = 32,
+ [0][1][RTW89_FCC][3] = 54,
+ [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] = 74,
- [0][1][RTW89_ETSI][4] = 26,
- [0][1][RTW89_MKK][4] = 32,
+ [0][1][RTW89_FCC][4] = 58,
+ [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] = 74,
- [0][1][RTW89_ETSI][5] = 26,
- [0][1][RTW89_MKK][5] = 32,
+ [0][1][RTW89_FCC][5] = 66,
+ [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] = 72,
- [0][1][RTW89_ETSI][6] = 26,
- [0][1][RTW89_MKK][6] = 32,
+ [0][1][RTW89_FCC][6] = 58,
+ [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] = 68,
- [0][1][RTW89_ETSI][7] = 26,
- [0][1][RTW89_MKK][7] = 32,
+ [0][1][RTW89_FCC][7] = 54,
+ [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] = 64,
- [0][1][RTW89_ETSI][8] = 26,
- [0][1][RTW89_MKK][8] = 32,
+ [0][1][RTW89_FCC][8] = 50,
+ [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] = 60,
- [0][1][RTW89_ETSI][9] = 26,
- [0][1][RTW89_MKK][9] = 32,
+ [0][1][RTW89_FCC][9] = 46,
+ [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] = 60,
- [0][1][RTW89_ETSI][10] = 26,
- [0][1][RTW89_MKK][10] = 32,
+ [0][1][RTW89_FCC][10] = 46,
+ [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] = 52,
- [0][1][RTW89_ETSI][11] = 26,
- [0][1][RTW89_MKK][11] = 32,
+ [0][1][RTW89_FCC][11] = 30,
+ [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] = 30,
- [0][1][RTW89_ETSI][12] = 22,
- [0][1][RTW89_MKK][12] = 26,
+ [0][1][RTW89_FCC][12] = 22,
+ [0][1][RTW89_ETSI][12] = 20,
+ [0][1][RTW89_MKK][12] = 24,
[0][1][RTW89_IC][12] = 30,
[0][1][RTW89_ACMA][12] = 20,
[0][1][RTW89_FCC][13] = 127,
@@ -17339,69 +17339,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_MKK][13] = 127,
[0][1][RTW89_IC][13] = 127,
[0][1][RTW89_ACMA][13] = 127,
- [1][0][RTW89_FCC][0] = 78,
- [1][0][RTW89_ETSI][0] = 48,
+ [1][0][RTW89_FCC][0] = 64,
+ [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] = 78,
- [1][0][RTW89_ETSI][1] = 48,
+ [1][0][RTW89_FCC][1] = 64,
+ [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] = 82,
- [1][0][RTW89_ETSI][2] = 48,
+ [1][0][RTW89_FCC][2] = 68,
+ [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] = 84,
- [1][0][RTW89_ETSI][3] = 48,
+ [1][0][RTW89_FCC][3] = 70,
+ [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] = 84,
- [1][0][RTW89_ETSI][4] = 48,
+ [1][0][RTW89_FCC][4] = 70,
+ [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] = 84,
- [1][0][RTW89_ETSI][5] = 48,
+ [1][0][RTW89_FCC][5] = 76,
+ [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] = 78,
- [1][0][RTW89_ETSI][6] = 46,
+ [1][0][RTW89_FCC][6] = 64,
+ [1][0][RTW89_ETSI][6] = 44,
[1][0][RTW89_MKK][6] = 48,
[1][0][RTW89_IC][6] = 78,
[1][0][RTW89_ACMA][6] = 44,
- [1][0][RTW89_FCC][7] = 78,
- [1][0][RTW89_ETSI][7] = 48,
+ [1][0][RTW89_FCC][7] = 64,
+ [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] = 78,
- [1][0][RTW89_ETSI][8] = 48,
+ [1][0][RTW89_FCC][8] = 64,
+ [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] = 74,
- [1][0][RTW89_ETSI][9] = 48,
+ [1][0][RTW89_FCC][9] = 60,
+ [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] = 74,
- [1][0][RTW89_ETSI][10] = 48,
+ [1][0][RTW89_FCC][10] = 60,
+ [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] = 72,
- [1][0][RTW89_ETSI][11] = 48,
+ [1][0][RTW89_FCC][11] = 42,
+ [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] = 38,
- [1][0][RTW89_ETSI][12] = 48,
- [1][0][RTW89_MKK][12] = 48,
+ [1][0][RTW89_FCC][12] = 30,
+ [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_FCC][13] = 127,
@@ -17409,69 +17409,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_MKK][13] = 127,
[1][0][RTW89_IC][13] = 127,
[1][0][RTW89_ACMA][13] = 127,
- [1][1][RTW89_FCC][0] = 66,
- [1][1][RTW89_ETSI][0] = 34,
- [1][1][RTW89_MKK][0] = 36,
+ [1][1][RTW89_FCC][0] = 46,
+ [1][1][RTW89_ETSI][0] = 32,
+ [1][1][RTW89_MKK][0] = 34,
[1][1][RTW89_IC][0] = 66,
[1][1][RTW89_ACMA][0] = 32,
- [1][1][RTW89_FCC][1] = 66,
- [1][1][RTW89_ETSI][1] = 36,
- [1][1][RTW89_MKK][1] = 36,
+ [1][1][RTW89_FCC][1] = 46,
+ [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] = 70,
- [1][1][RTW89_ETSI][2] = 36,
- [1][1][RTW89_MKK][2] = 36,
+ [1][1][RTW89_FCC][2] = 50,
+ [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] = 74,
- [1][1][RTW89_ETSI][3] = 36,
- [1][1][RTW89_MKK][3] = 36,
+ [1][1][RTW89_FCC][3] = 54,
+ [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] = 74,
- [1][1][RTW89_ETSI][4] = 36,
- [1][1][RTW89_MKK][4] = 36,
+ [1][1][RTW89_FCC][4] = 58,
+ [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] = 74,
- [1][1][RTW89_ETSI][5] = 36,
- [1][1][RTW89_MKK][5] = 36,
+ [1][1][RTW89_FCC][5] = 66,
+ [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] = 74,
- [1][1][RTW89_ETSI][6] = 36,
- [1][1][RTW89_MKK][6] = 36,
+ [1][1][RTW89_FCC][6] = 58,
+ [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] = 74,
- [1][1][RTW89_ETSI][7] = 36,
- [1][1][RTW89_MKK][7] = 36,
+ [1][1][RTW89_FCC][7] = 54,
+ [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] = 70,
- [1][1][RTW89_ETSI][8] = 36,
- [1][1][RTW89_MKK][8] = 36,
+ [1][1][RTW89_FCC][8] = 50,
+ [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] = 66,
- [1][1][RTW89_ETSI][9] = 36,
- [1][1][RTW89_MKK][9] = 36,
+ [1][1][RTW89_FCC][9] = 46,
+ [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] = 66,
- [1][1][RTW89_ETSI][10] = 36,
- [1][1][RTW89_MKK][10] = 36,
+ [1][1][RTW89_FCC][10] = 46,
+ [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_FCC][11] = 48,
- [1][1][RTW89_ETSI][11] = 36,
- [1][1][RTW89_MKK][11] = 36,
+ [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] = 32,
- [1][1][RTW89_ETSI][12] = 36,
- [1][1][RTW89_MKK][12] = 36,
+ [1][1][RTW89_FCC][12] = 24,
+ [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_FCC][13] = 127,
@@ -17479,69 +17479,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_MKK][13] = 127,
[1][1][RTW89_IC][13] = 127,
[1][1][RTW89_ACMA][13] = 127,
- [2][0][RTW89_FCC][0] = 78,
- [2][0][RTW89_ETSI][0] = 60,
- [2][0][RTW89_MKK][0] = 60,
+ [2][0][RTW89_FCC][0] = 64,
+ [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] = 78,
- [2][0][RTW89_ETSI][1] = 60,
- [2][0][RTW89_MKK][1] = 60,
+ [2][0][RTW89_FCC][1] = 64,
+ [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] = 80,
- [2][0][RTW89_ETSI][2] = 60,
- [2][0][RTW89_MKK][2] = 60,
+ [2][0][RTW89_FCC][2] = 66,
+ [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] = 80,
- [2][0][RTW89_ETSI][3] = 60,
- [2][0][RTW89_MKK][3] = 60,
+ [2][0][RTW89_FCC][3] = 66,
+ [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] = 80,
- [2][0][RTW89_ETSI][4] = 60,
- [2][0][RTW89_MKK][4] = 60,
+ [2][0][RTW89_FCC][4] = 66,
+ [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] = 84,
- [2][0][RTW89_ETSI][5] = 60,
- [2][0][RTW89_MKK][5] = 60,
+ [2][0][RTW89_FCC][5] = 76,
+ [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] = 76,
- [2][0][RTW89_ETSI][6] = 58,
- [2][0][RTW89_MKK][6] = 60,
+ [2][0][RTW89_FCC][6] = 62,
+ [2][0][RTW89_ETSI][6] = 56,
+ [2][0][RTW89_MKK][6] = 58,
[2][0][RTW89_IC][6] = 76,
[2][0][RTW89_ACMA][6] = 56,
- [2][0][RTW89_FCC][7] = 76,
- [2][0][RTW89_ETSI][7] = 60,
- [2][0][RTW89_MKK][7] = 60,
+ [2][0][RTW89_FCC][7] = 62,
+ [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] = 76,
- [2][0][RTW89_ETSI][8] = 60,
- [2][0][RTW89_MKK][8] = 60,
+ [2][0][RTW89_FCC][8] = 62,
+ [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] = 74,
- [2][0][RTW89_ETSI][9] = 60,
- [2][0][RTW89_MKK][9] = 60,
+ [2][0][RTW89_FCC][9] = 60,
+ [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] = 74,
- [2][0][RTW89_ETSI][10] = 60,
- [2][0][RTW89_MKK][10] = 60,
+ [2][0][RTW89_FCC][10] = 60,
+ [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] = 66,
- [2][0][RTW89_ETSI][11] = 60,
- [2][0][RTW89_MKK][11] = 60,
+ [2][0][RTW89_FCC][11] = 42,
+ [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] = 56,
- [2][0][RTW89_ETSI][12] = 60,
- [2][0][RTW89_MKK][12] = 60,
+ [2][0][RTW89_FCC][12] = 38,
+ [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_FCC][13] = 127,
@@ -17549,69 +17549,69 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][0][RTW89_MKK][13] = 127,
[2][0][RTW89_IC][13] = 127,
[2][0][RTW89_ACMA][13] = 127,
- [2][1][RTW89_FCC][0] = 70,
- [2][1][RTW89_ETSI][0] = 48,
- [2][1][RTW89_MKK][0] = 48,
+ [2][1][RTW89_FCC][0] = 46,
+ [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] = 70,
- [2][1][RTW89_ETSI][1] = 48,
- [2][1][RTW89_MKK][1] = 48,
+ [2][1][RTW89_FCC][1] = 46,
+ [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] = 74,
- [2][1][RTW89_ETSI][2] = 48,
- [2][1][RTW89_MKK][2] = 48,
+ [2][1][RTW89_FCC][2] = 50,
+ [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] = 78,
- [2][1][RTW89_ETSI][3] = 48,
- [2][1][RTW89_MKK][3] = 48,
+ [2][1][RTW89_FCC][3] = 54,
+ [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] = 80,
- [2][1][RTW89_ETSI][4] = 48,
- [2][1][RTW89_MKK][4] = 48,
+ [2][1][RTW89_FCC][4] = 56,
+ [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] = 80,
- [2][1][RTW89_ETSI][5] = 48,
- [2][1][RTW89_MKK][5] = 48,
+ [2][1][RTW89_FCC][5] = 72,
+ [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] = 78,
- [2][1][RTW89_ETSI][6] = 46,
- [2][1][RTW89_MKK][6] = 48,
+ [2][1][RTW89_FCC][6] = 54,
+ [2][1][RTW89_ETSI][6] = 44,
+ [2][1][RTW89_MKK][6] = 46,
[2][1][RTW89_IC][6] = 78,
[2][1][RTW89_ACMA][6] = 44,
- [2][1][RTW89_FCC][7] = 78,
- [2][1][RTW89_ETSI][7] = 48,
- [2][1][RTW89_MKK][7] = 48,
+ [2][1][RTW89_FCC][7] = 54,
+ [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] = 74,
- [2][1][RTW89_ETSI][8] = 48,
- [2][1][RTW89_MKK][8] = 48,
+ [2][1][RTW89_FCC][8] = 50,
+ [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] = 70,
- [2][1][RTW89_ETSI][9] = 48,
- [2][1][RTW89_MKK][9] = 48,
+ [2][1][RTW89_FCC][9] = 46,
+ [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] = 70,
- [2][1][RTW89_ETSI][10] = 48,
- [2][1][RTW89_MKK][10] = 48,
+ [2][1][RTW89_FCC][10] = 46,
+ [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] = 60,
- [2][1][RTW89_ETSI][11] = 48,
- [2][1][RTW89_MKK][11] = 48,
+ [2][1][RTW89_FCC][11] = 30,
+ [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] = 44,
- [2][1][RTW89_ETSI][12] = 46,
- [2][1][RTW89_MKK][12] = 48,
+ [2][1][RTW89_FCC][12] = 26,
+ [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_FCC][13] = 127,
@@ -17625,10 +17625,10 @@ 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] = 24,
- [0][0][RTW89_WW][6] = 24,
- [0][0][RTW89_WW][8] = 24,
- [0][0][RTW89_WW][10] = 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,
@@ -17636,21 +17636,21 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_WW][19] = 24,
[0][0][RTW89_WW][21] = 24,
[0][0][RTW89_WW][23] = 24,
- [0][0][RTW89_WW][25] = 32,
- [0][0][RTW89_WW][27] = 32,
- [0][0][RTW89_WW][29] = 32,
+ [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][38] = 30,
- [0][0][RTW89_WW][40] = 30,
- [0][0][RTW89_WW][42] = 30,
- [0][0][RTW89_WW][44] = 30,
- [0][0][RTW89_WW][46] = 30,
- [0][0][RTW89_WW][48] = 32,
- [0][0][RTW89_WW][50] = 32,
- [0][0][RTW89_WW][52] = 32,
+ [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][1][RTW89_WW][2] = 4,
[0][1][RTW89_WW][4] = 0,
@@ -17664,21 +17664,21 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_WW][19] = 12,
[0][1][RTW89_WW][21] = 12,
[0][1][RTW89_WW][23] = 12,
- [0][1][RTW89_WW][25] = 20,
- [0][1][RTW89_WW][27] = 18,
- [0][1][RTW89_WW][29] = 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] = 34,
- [0][1][RTW89_WW][38] = 18,
- [0][1][RTW89_WW][40] = 18,
- [0][1][RTW89_WW][42] = 18,
- [0][1][RTW89_WW][44] = 18,
- [0][1][RTW89_WW][46] = 18,
- [0][1][RTW89_WW][48] = 20,
- [0][1][RTW89_WW][50] = 20,
- [0][1][RTW89_WW][52] = 20,
+ [0][1][RTW89_WW][37] = 30,
+ [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,
@@ -17692,21 +17692,21 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_WW][19] = 34,
[1][0][RTW89_WW][21] = 34,
[1][0][RTW89_WW][23] = 34,
- [1][0][RTW89_WW][25] = 42,
- [1][0][RTW89_WW][27] = 44,
- [1][0][RTW89_WW][29] = 44,
+ [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] = 52,
- [1][0][RTW89_WW][38] = 30,
- [1][0][RTW89_WW][40] = 30,
- [1][0][RTW89_WW][42] = 30,
- [1][0][RTW89_WW][44] = 30,
- [1][0][RTW89_WW][46] = 30,
- [1][0][RTW89_WW][48] = 44,
- [1][0][RTW89_WW][50] = 44,
- [1][0][RTW89_WW][52] = 44,
+ [1][0][RTW89_WW][37] = 56,
+ [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][1][RTW89_WW][2] = 14,
[1][1][RTW89_WW][4] = 10,
@@ -17720,55 +17720,55 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_WW][19] = 22,
[1][1][RTW89_WW][21] = 22,
[1][1][RTW89_WW][23] = 22,
- [1][1][RTW89_WW][25] = 30,
- [1][1][RTW89_WW][27] = 32,
- [1][1][RTW89_WW][29] = 32,
+ [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] = 42,
- [1][1][RTW89_WW][38] = 18,
- [1][1][RTW89_WW][40] = 18,
- [1][1][RTW89_WW][42] = 18,
- [1][1][RTW89_WW][44] = 18,
- [1][1][RTW89_WW][46] = 18,
- [1][1][RTW89_WW][48] = 32,
- [1][1][RTW89_WW][50] = 32,
- [1][1][RTW89_WW][52] = 32,
+ [1][1][RTW89_WW][37] = 40,
+ [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] = 48,
- [2][0][RTW89_WW][10] = 48,
- [2][0][RTW89_WW][12] = 46,
- [2][0][RTW89_WW][14] = 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,
- [2][0][RTW89_WW][25] = 54,
- [2][0][RTW89_WW][27] = 54,
- [2][0][RTW89_WW][29] = 54,
+ [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] = 66,
- [2][0][RTW89_WW][38] = 30,
- [2][0][RTW89_WW][40] = 30,
- [2][0][RTW89_WW][42] = 30,
- [2][0][RTW89_WW][44] = 30,
- [2][0][RTW89_WW][46] = 30,
- [2][0][RTW89_WW][48] = 56,
- [2][0][RTW89_WW][50] = 56,
- [2][0][RTW89_WW][52] = 56,
+ [2][0][RTW89_WW][37] = 62,
+ [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] = 34,
- [2][1][RTW89_WW][10] = 34,
+ [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,
@@ -17776,857 +17776,857 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_WW][19] = 36,
[2][1][RTW89_WW][21] = 36,
[2][1][RTW89_WW][23] = 36,
- [2][1][RTW89_WW][25] = 42,
- [2][1][RTW89_WW][27] = 42,
- [2][1][RTW89_WW][29] = 42,
+ [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][37] = 50,
- [2][1][RTW89_WW][38] = 18,
- [2][1][RTW89_WW][40] = 18,
- [2][1][RTW89_WW][42] = 18,
- [2][1][RTW89_WW][44] = 18,
- [2][1][RTW89_WW][46] = 18,
- [2][1][RTW89_WW][48] = 44,
- [2][1][RTW89_WW][50] = 44,
- [2][1][RTW89_WW][52] = 44,
- [0][0][RTW89_FCC][0] = 52,
- [0][0][RTW89_ETSI][0] = 32,
- [0][0][RTW89_MKK][0] = 26,
+ [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,
+ [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] = 52,
- [0][0][RTW89_ETSI][2] = 32,
- [0][0][RTW89_MKK][2] = 26,
+ [0][0][RTW89_FCC][2] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][4] = 32,
- [0][0][RTW89_MKK][4] = 26,
+ [0][0][RTW89_FCC][4] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][6] = 32,
- [0][0][RTW89_MKK][6] = 26,
+ [0][0][RTW89_FCC][6] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][8] = 30,
- [0][0][RTW89_MKK][8] = 26,
+ [0][0][RTW89_FCC][8] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][10] = 30,
- [0][0][RTW89_MKK][10] = 26,
+ [0][0][RTW89_FCC][10] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][12] = 30,
- [0][0][RTW89_MKK][12] = 24,
+ [0][0][RTW89_FCC][12] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][14] = 30,
- [0][0][RTW89_MKK][14] = 24,
+ [0][0][RTW89_FCC][14] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][15] = 32,
- [0][0][RTW89_MKK][15] = 46,
+ [0][0][RTW89_FCC][15] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][17] = 32,
- [0][0][RTW89_MKK][17] = 48,
+ [0][0][RTW89_FCC][17] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][19] = 32,
- [0][0][RTW89_MKK][19] = 48,
+ [0][0][RTW89_FCC][19] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][21] = 32,
- [0][0][RTW89_MKK][21] = 48,
+ [0][0][RTW89_FCC][21] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][23] = 32,
- [0][0][RTW89_MKK][23] = 48,
+ [0][0][RTW89_FCC][23] = 44,
+ [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] = 52,
- [0][0][RTW89_ETSI][25] = 32,
- [0][0][RTW89_MKK][25] = 48,
+ [0][0][RTW89_FCC][25] = 44,
+ [0][0][RTW89_ETSI][25] = 30,
+ [0][0][RTW89_MKK][25] = 58,
[0][0][RTW89_IC][25] = 127,
[0][0][RTW89_ACMA][25] = 127,
- [0][0][RTW89_FCC][27] = 52,
- [0][0][RTW89_ETSI][27] = 32,
- [0][0][RTW89_MKK][27] = 48,
+ [0][0][RTW89_FCC][27] = 44,
+ [0][0][RTW89_ETSI][27] = 30,
+ [0][0][RTW89_MKK][27] = 58,
[0][0][RTW89_IC][27] = 127,
[0][0][RTW89_ACMA][27] = 127,
- [0][0][RTW89_FCC][29] = 52,
- [0][0][RTW89_ETSI][29] = 32,
- [0][0][RTW89_MKK][29] = 48,
+ [0][0][RTW89_FCC][29] = 44,
+ [0][0][RTW89_ETSI][29] = 30,
+ [0][0][RTW89_MKK][29] = 58,
[0][0][RTW89_IC][29] = 127,
[0][0][RTW89_ACMA][29] = 127,
- [0][0][RTW89_FCC][31] = 52,
- [0][0][RTW89_ETSI][31] = 32,
- [0][0][RTW89_MKK][31] = 48,
+ [0][0][RTW89_FCC][31] = 44,
+ [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_FCC][33] = 52,
- [0][0][RTW89_ETSI][33] = 32,
- [0][0][RTW89_MKK][33] = 48,
+ [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_FCC][35] = 52,
- [0][0][RTW89_ETSI][35] = 32,
- [0][0][RTW89_MKK][35] = 48,
+ [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] = 52,
+ [0][0][RTW89_FCC][37] = 44,
[0][0][RTW89_ETSI][37] = 127,
- [0][0][RTW89_MKK][37] = 44,
+ [0][0][RTW89_MKK][37] = 58,
[0][0][RTW89_IC][37] = 52,
[0][0][RTW89_ACMA][37] = 52,
- [0][0][RTW89_FCC][38] = 84,
- [0][0][RTW89_ETSI][38] = 30,
+ [0][0][RTW89_FCC][38] = 76,
+ [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] = 84,
- [0][0][RTW89_ETSI][40] = 30,
+ [0][0][RTW89_FCC][40] = 76,
+ [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] = 84,
- [0][0][RTW89_ETSI][42] = 30,
+ [0][0][RTW89_FCC][42] = 76,
+ [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] = 84,
- [0][0][RTW89_ETSI][44] = 30,
+ [0][0][RTW89_FCC][44] = 76,
+ [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] = 84,
- [0][0][RTW89_ETSI][46] = 30,
+ [0][0][RTW89_FCC][46] = 76,
+ [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] = 32,
+ [0][0][RTW89_FCC][48] = 24,
[0][0][RTW89_ETSI][48] = 127,
[0][0][RTW89_MKK][48] = 127,
[0][0][RTW89_IC][48] = 127,
[0][0][RTW89_ACMA][48] = 127,
- [0][0][RTW89_FCC][50] = 32,
+ [0][0][RTW89_FCC][50] = 24,
[0][0][RTW89_ETSI][50] = 127,
[0][0][RTW89_MKK][50] = 127,
[0][0][RTW89_IC][50] = 127,
[0][0][RTW89_ACMA][50] = 127,
- [0][0][RTW89_FCC][52] = 32,
+ [0][0][RTW89_FCC][52] = 24,
[0][0][RTW89_ETSI][52] = 127,
[0][0][RTW89_MKK][52] = 127,
[0][0][RTW89_IC][52] = 127,
[0][0][RTW89_ACMA][52] = 127,
- [0][1][RTW89_FCC][0] = 34,
- [0][1][RTW89_ETSI][0] = 20,
- [0][1][RTW89_MKK][0] = 12,
+ [0][1][RTW89_FCC][0] = 26,
+ [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] = 38,
- [0][1][RTW89_ETSI][2] = 20,
- [0][1][RTW89_MKK][2] = 12,
+ [0][1][RTW89_FCC][2] = 30,
+ [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] = 34,
- [0][1][RTW89_ETSI][4] = 20,
- [0][1][RTW89_MKK][4] = 14,
+ [0][1][RTW89_FCC][4] = 26,
+ [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] = 34,
- [0][1][RTW89_ETSI][6] = 20,
- [0][1][RTW89_MKK][6] = 14,
+ [0][1][RTW89_FCC][6] = 26,
+ [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] = 34,
- [0][1][RTW89_ETSI][8] = 18,
- [0][1][RTW89_MKK][8] = 14,
+ [0][1][RTW89_FCC][8] = 26,
+ [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] = 34,
- [0][1][RTW89_ETSI][10] = 18,
- [0][1][RTW89_MKK][10] = 14,
+ [0][1][RTW89_FCC][10] = 26,
+ [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_FCC][12] = 38,
- [0][1][RTW89_ETSI][12] = 18,
- [0][1][RTW89_MKK][12] = 12,
+ [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] = 34,
- [0][1][RTW89_ETSI][14] = 18,
- [0][1][RTW89_MKK][14] = 12,
+ [0][1][RTW89_FCC][14] = 26,
+ [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] = 34,
- [0][1][RTW89_ETSI][15] = 20,
- [0][1][RTW89_MKK][15] = 32,
+ [0][1][RTW89_FCC][15] = 26,
+ [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] = 34,
- [0][1][RTW89_ETSI][17] = 20,
- [0][1][RTW89_MKK][17] = 34,
+ [0][1][RTW89_FCC][17] = 26,
+ [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] = 38,
- [0][1][RTW89_ETSI][19] = 20,
- [0][1][RTW89_MKK][19] = 34,
+ [0][1][RTW89_FCC][19] = 30,
+ [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] = 38,
- [0][1][RTW89_ETSI][21] = 20,
- [0][1][RTW89_MKK][21] = 34,
+ [0][1][RTW89_FCC][21] = 30,
+ [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] = 38,
- [0][1][RTW89_ETSI][23] = 20,
- [0][1][RTW89_MKK][23] = 34,
+ [0][1][RTW89_FCC][23] = 30,
+ [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] = 38,
- [0][1][RTW89_ETSI][25] = 20,
- [0][1][RTW89_MKK][25] = 34,
+ [0][1][RTW89_FCC][25] = 30,
+ [0][1][RTW89_ETSI][25] = 18,
+ [0][1][RTW89_MKK][25] = 44,
[0][1][RTW89_IC][25] = 127,
[0][1][RTW89_ACMA][25] = 127,
- [0][1][RTW89_FCC][27] = 38,
- [0][1][RTW89_ETSI][27] = 18,
- [0][1][RTW89_MKK][27] = 34,
+ [0][1][RTW89_FCC][27] = 30,
+ [0][1][RTW89_ETSI][27] = 16,
+ [0][1][RTW89_MKK][27] = 44,
[0][1][RTW89_IC][27] = 127,
[0][1][RTW89_ACMA][27] = 127,
- [0][1][RTW89_FCC][29] = 38,
- [0][1][RTW89_ETSI][29] = 18,
- [0][1][RTW89_MKK][29] = 34,
+ [0][1][RTW89_FCC][29] = 30,
+ [0][1][RTW89_ETSI][29] = 16,
+ [0][1][RTW89_MKK][29] = 44,
[0][1][RTW89_IC][29] = 127,
[0][1][RTW89_ACMA][29] = 127,
- [0][1][RTW89_FCC][31] = 38,
- [0][1][RTW89_ETSI][31] = 18,
- [0][1][RTW89_MKK][31] = 34,
+ [0][1][RTW89_FCC][31] = 30,
+ [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] = 34,
- [0][1][RTW89_ETSI][33] = 18,
- [0][1][RTW89_MKK][33] = 34,
+ [0][1][RTW89_FCC][33] = 26,
+ [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] = 34,
- [0][1][RTW89_ETSI][35] = 18,
- [0][1][RTW89_MKK][35] = 34,
+ [0][1][RTW89_FCC][35] = 26,
+ [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] = 38,
+ [0][1][RTW89_FCC][37] = 30,
[0][1][RTW89_ETSI][37] = 127,
- [0][1][RTW89_MKK][37] = 34,
+ [0][1][RTW89_MKK][37] = 44,
[0][1][RTW89_IC][37] = 38,
[0][1][RTW89_ACMA][37] = 38,
- [0][1][RTW89_FCC][38] = 82,
- [0][1][RTW89_ETSI][38] = 18,
+ [0][1][RTW89_FCC][38] = 74,
+ [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] = 82,
- [0][1][RTW89_ETSI][40] = 18,
+ [0][1][RTW89_FCC][40] = 74,
+ [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] = 82,
- [0][1][RTW89_ETSI][42] = 18,
+ [0][1][RTW89_FCC][42] = 74,
+ [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] = 82,
- [0][1][RTW89_ETSI][44] = 18,
+ [0][1][RTW89_FCC][44] = 74,
+ [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] = 82,
- [0][1][RTW89_ETSI][46] = 18,
+ [0][1][RTW89_FCC][46] = 74,
+ [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] = 20,
+ [0][1][RTW89_FCC][48] = 12,
[0][1][RTW89_ETSI][48] = 127,
[0][1][RTW89_MKK][48] = 127,
[0][1][RTW89_IC][48] = 127,
[0][1][RTW89_ACMA][48] = 127,
- [0][1][RTW89_FCC][50] = 20,
+ [0][1][RTW89_FCC][50] = 12,
[0][1][RTW89_ETSI][50] = 127,
[0][1][RTW89_MKK][50] = 127,
[0][1][RTW89_IC][50] = 127,
[0][1][RTW89_ACMA][50] = 127,
- [0][1][RTW89_FCC][52] = 20,
+ [0][1][RTW89_FCC][52] = 12,
[0][1][RTW89_ETSI][52] = 127,
[0][1][RTW89_MKK][52] = 127,
[0][1][RTW89_IC][52] = 127,
[0][1][RTW89_ACMA][52] = 127,
- [1][0][RTW89_FCC][0] = 62,
- [1][0][RTW89_ETSI][0] = 42,
- [1][0][RTW89_MKK][0] = 36,
+ [1][0][RTW89_FCC][0] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][2] = 42,
- [1][0][RTW89_MKK][2] = 36,
+ [1][0][RTW89_FCC][2] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][4] = 42,
- [1][0][RTW89_MKK][4] = 34,
+ [1][0][RTW89_FCC][4] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][6] = 42,
- [1][0][RTW89_MKK][6] = 34,
+ [1][0][RTW89_FCC][6] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][8] = 42,
- [1][0][RTW89_MKK][8] = 36,
+ [1][0][RTW89_FCC][8] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][10] = 42,
- [1][0][RTW89_MKK][10] = 36,
+ [1][0][RTW89_FCC][10] = 54,
+ [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] = 64,
- [1][0][RTW89_ETSI][12] = 42,
- [1][0][RTW89_MKK][12] = 36,
+ [1][0][RTW89_FCC][12] = 56,
+ [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] = 62,
- [1][0][RTW89_ETSI][14] = 42,
- [1][0][RTW89_MKK][14] = 36,
+ [1][0][RTW89_FCC][14] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][15] = 42,
- [1][0][RTW89_MKK][15] = 54,
+ [1][0][RTW89_FCC][15] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][17] = 42,
- [1][0][RTW89_MKK][17] = 58,
+ [1][0][RTW89_FCC][17] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][19] = 42,
- [1][0][RTW89_MKK][19] = 58,
+ [1][0][RTW89_FCC][19] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][21] = 42,
- [1][0][RTW89_MKK][21] = 58,
+ [1][0][RTW89_FCC][21] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][23] = 42,
- [1][0][RTW89_MKK][23] = 58,
+ [1][0][RTW89_FCC][23] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][25] = 42,
- [1][0][RTW89_MKK][25] = 58,
+ [1][0][RTW89_FCC][25] = 54,
+ [1][0][RTW89_ETSI][25] = 40,
+ [1][0][RTW89_MKK][25] = 68,
[1][0][RTW89_IC][25] = 127,
[1][0][RTW89_ACMA][25] = 127,
- [1][0][RTW89_FCC][27] = 62,
- [1][0][RTW89_ETSI][27] = 44,
- [1][0][RTW89_MKK][27] = 58,
+ [1][0][RTW89_FCC][27] = 54,
+ [1][0][RTW89_ETSI][27] = 42,
+ [1][0][RTW89_MKK][27] = 68,
[1][0][RTW89_IC][27] = 127,
[1][0][RTW89_ACMA][27] = 127,
- [1][0][RTW89_FCC][29] = 62,
- [1][0][RTW89_ETSI][29] = 44,
- [1][0][RTW89_MKK][29] = 58,
+ [1][0][RTW89_FCC][29] = 54,
+ [1][0][RTW89_ETSI][29] = 42,
+ [1][0][RTW89_MKK][29] = 68,
[1][0][RTW89_IC][29] = 127,
[1][0][RTW89_ACMA][29] = 127,
- [1][0][RTW89_FCC][31] = 62,
- [1][0][RTW89_ETSI][31] = 44,
- [1][0][RTW89_MKK][31] = 58,
+ [1][0][RTW89_FCC][31] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][33] = 44,
- [1][0][RTW89_MKK][33] = 58,
+ [1][0][RTW89_FCC][33] = 54,
+ [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] = 62,
- [1][0][RTW89_ETSI][35] = 44,
- [1][0][RTW89_MKK][35] = 58,
+ [1][0][RTW89_FCC][35] = 54,
+ [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] = 64,
+ [1][0][RTW89_FCC][37] = 56,
[1][0][RTW89_ETSI][37] = 127,
- [1][0][RTW89_MKK][37] = 52,
+ [1][0][RTW89_MKK][37] = 68,
[1][0][RTW89_IC][37] = 64,
[1][0][RTW89_ACMA][37] = 64,
- [1][0][RTW89_FCC][38] = 84,
- [1][0][RTW89_ETSI][38] = 30,
+ [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_FCC][40] = 84,
- [1][0][RTW89_ETSI][40] = 30,
+ [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] = 84,
- [1][0][RTW89_ETSI][42] = 30,
+ [1][0][RTW89_FCC][42] = 76,
+ [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] = 84,
- [1][0][RTW89_ETSI][44] = 30,
+ [1][0][RTW89_FCC][44] = 76,
+ [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] = 84,
- [1][0][RTW89_ETSI][46] = 30,
+ [1][0][RTW89_FCC][46] = 76,
+ [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] = 44,
+ [1][0][RTW89_FCC][48] = 36,
[1][0][RTW89_ETSI][48] = 127,
[1][0][RTW89_MKK][48] = 127,
[1][0][RTW89_IC][48] = 127,
[1][0][RTW89_ACMA][48] = 127,
- [1][0][RTW89_FCC][50] = 44,
+ [1][0][RTW89_FCC][50] = 36,
[1][0][RTW89_ETSI][50] = 127,
[1][0][RTW89_MKK][50] = 127,
[1][0][RTW89_IC][50] = 127,
[1][0][RTW89_ACMA][50] = 127,
- [1][0][RTW89_FCC][52] = 44,
+ [1][0][RTW89_FCC][52] = 36,
[1][0][RTW89_ETSI][52] = 127,
[1][0][RTW89_MKK][52] = 127,
[1][0][RTW89_IC][52] = 127,
[1][0][RTW89_ACMA][52] = 127,
- [1][1][RTW89_FCC][0] = 42,
- [1][1][RTW89_ETSI][0] = 32,
- [1][1][RTW89_MKK][0] = 22,
+ [1][1][RTW89_FCC][0] = 34,
+ [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] = 44,
- [1][1][RTW89_ETSI][2] = 32,
- [1][1][RTW89_MKK][2] = 22,
+ [1][1][RTW89_FCC][2] = 36,
+ [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] = 42,
- [1][1][RTW89_ETSI][4] = 32,
- [1][1][RTW89_MKK][4] = 20,
+ [1][1][RTW89_FCC][4] = 34,
+ [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] = 42,
- [1][1][RTW89_ETSI][6] = 32,
- [1][1][RTW89_MKK][6] = 20,
+ [1][1][RTW89_FCC][6] = 34,
+ [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] = 44,
- [1][1][RTW89_ETSI][8] = 32,
+ [1][1][RTW89_FCC][8] = 36,
+ [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] = 44,
- [1][1][RTW89_ETSI][10] = 32,
+ [1][1][RTW89_FCC][10] = 36,
+ [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] = 46,
- [1][1][RTW89_ETSI][12] = 32,
- [1][1][RTW89_MKK][12] = 22,
+ [1][1][RTW89_FCC][12] = 38,
+ [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] = 42,
- [1][1][RTW89_ETSI][14] = 32,
- [1][1][RTW89_MKK][14] = 22,
+ [1][1][RTW89_FCC][14] = 34,
+ [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] = 42,
- [1][1][RTW89_ETSI][15] = 30,
- [1][1][RTW89_MKK][15] = 42,
+ [1][1][RTW89_FCC][15] = 34,
+ [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] = 42,
- [1][1][RTW89_ETSI][17] = 30,
- [1][1][RTW89_MKK][17] = 44,
+ [1][1][RTW89_FCC][17] = 34,
+ [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] = 42,
- [1][1][RTW89_ETSI][19] = 30,
- [1][1][RTW89_MKK][19] = 44,
+ [1][1][RTW89_FCC][19] = 34,
+ [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] = 42,
- [1][1][RTW89_ETSI][21] = 30,
- [1][1][RTW89_MKK][21] = 44,
+ [1][1][RTW89_FCC][21] = 34,
+ [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] = 42,
- [1][1][RTW89_ETSI][23] = 30,
- [1][1][RTW89_MKK][23] = 44,
+ [1][1][RTW89_FCC][23] = 34,
+ [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] = 42,
- [1][1][RTW89_ETSI][25] = 30,
- [1][1][RTW89_MKK][25] = 44,
+ [1][1][RTW89_FCC][25] = 34,
+ [1][1][RTW89_ETSI][25] = 28,
+ [1][1][RTW89_MKK][25] = 58,
[1][1][RTW89_IC][25] = 127,
[1][1][RTW89_ACMA][25] = 127,
- [1][1][RTW89_FCC][27] = 42,
- [1][1][RTW89_ETSI][27] = 32,
- [1][1][RTW89_MKK][27] = 44,
+ [1][1][RTW89_FCC][27] = 34,
+ [1][1][RTW89_ETSI][27] = 30,
+ [1][1][RTW89_MKK][27] = 58,
[1][1][RTW89_IC][27] = 127,
[1][1][RTW89_ACMA][27] = 127,
- [1][1][RTW89_FCC][29] = 42,
- [1][1][RTW89_ETSI][29] = 32,
- [1][1][RTW89_MKK][29] = 44,
+ [1][1][RTW89_FCC][29] = 34,
+ [1][1][RTW89_ETSI][29] = 30,
+ [1][1][RTW89_MKK][29] = 58,
[1][1][RTW89_IC][29] = 127,
[1][1][RTW89_ACMA][29] = 127,
- [1][1][RTW89_FCC][31] = 42,
- [1][1][RTW89_ETSI][31] = 32,
- [1][1][RTW89_MKK][31] = 44,
+ [1][1][RTW89_FCC][31] = 34,
+ [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] = 40,
- [1][1][RTW89_ETSI][33] = 32,
- [1][1][RTW89_MKK][33] = 44,
+ [1][1][RTW89_FCC][33] = 32,
+ [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] = 40,
- [1][1][RTW89_ETSI][35] = 32,
- [1][1][RTW89_MKK][35] = 44,
+ [1][1][RTW89_FCC][35] = 32,
+ [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] = 48,
+ [1][1][RTW89_FCC][37] = 40,
[1][1][RTW89_ETSI][37] = 127,
- [1][1][RTW89_MKK][37] = 42,
+ [1][1][RTW89_MKK][37] = 58,
[1][1][RTW89_IC][37] = 48,
[1][1][RTW89_ACMA][37] = 48,
- [1][1][RTW89_FCC][38] = 84,
- [1][1][RTW89_ETSI][38] = 18,
+ [1][1][RTW89_FCC][38] = 76,
+ [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] = 84,
- [1][1][RTW89_ETSI][40] = 18,
+ [1][1][RTW89_FCC][40] = 76,
+ [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] = 84,
- [1][1][RTW89_ETSI][42] = 18,
+ [1][1][RTW89_FCC][42] = 76,
+ [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] = 84,
- [1][1][RTW89_ETSI][44] = 18,
+ [1][1][RTW89_FCC][44] = 76,
+ [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] = 84,
- [1][1][RTW89_ETSI][46] = 18,
+ [1][1][RTW89_FCC][46] = 76,
+ [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] = 32,
+ [1][1][RTW89_FCC][48] = 24,
[1][1][RTW89_ETSI][48] = 127,
[1][1][RTW89_MKK][48] = 127,
[1][1][RTW89_IC][48] = 127,
[1][1][RTW89_ACMA][48] = 127,
- [1][1][RTW89_FCC][50] = 32,
+ [1][1][RTW89_FCC][50] = 24,
[1][1][RTW89_ETSI][50] = 127,
[1][1][RTW89_MKK][50] = 127,
[1][1][RTW89_IC][50] = 127,
[1][1][RTW89_ACMA][50] = 127,
- [1][1][RTW89_FCC][52] = 32,
+ [1][1][RTW89_FCC][52] = 24,
[1][1][RTW89_ETSI][52] = 127,
[1][1][RTW89_MKK][52] = 127,
[1][1][RTW89_IC][52] = 127,
[1][1][RTW89_ACMA][52] = 127,
- [2][0][RTW89_FCC][0] = 70,
- [2][0][RTW89_ETSI][0] = 54,
- [2][0][RTW89_MKK][0] = 48,
+ [2][0][RTW89_FCC][0] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][2] = 54,
- [2][0][RTW89_MKK][2] = 48,
+ [2][0][RTW89_FCC][2] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][4] = 54,
- [2][0][RTW89_MKK][4] = 48,
+ [2][0][RTW89_FCC][4] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][6] = 54,
- [2][0][RTW89_MKK][6] = 48,
+ [2][0][RTW89_FCC][6] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][8] = 54,
- [2][0][RTW89_MKK][8] = 48,
+ [2][0][RTW89_FCC][8] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][10] = 54,
- [2][0][RTW89_MKK][10] = 48,
+ [2][0][RTW89_FCC][10] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][12] = 54,
- [2][0][RTW89_MKK][12] = 46,
+ [2][0][RTW89_FCC][12] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][14] = 54,
- [2][0][RTW89_MKK][14] = 46,
+ [2][0][RTW89_FCC][14] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][15] = 54,
+ [2][0][RTW89_FCC][15] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][17] = 54,
- [2][0][RTW89_MKK][17] = 70,
+ [2][0][RTW89_FCC][17] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][19] = 54,
- [2][0][RTW89_MKK][19] = 70,
+ [2][0][RTW89_FCC][19] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][21] = 54,
- [2][0][RTW89_MKK][21] = 70,
+ [2][0][RTW89_FCC][21] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][23] = 54,
- [2][0][RTW89_MKK][23] = 70,
+ [2][0][RTW89_FCC][23] = 62,
+ [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] = 70,
- [2][0][RTW89_ETSI][25] = 54,
- [2][0][RTW89_MKK][25] = 70,
+ [2][0][RTW89_FCC][25] = 62,
+ [2][0][RTW89_ETSI][25] = 52,
+ [2][0][RTW89_MKK][25] = 74,
[2][0][RTW89_IC][25] = 127,
[2][0][RTW89_ACMA][25] = 127,
- [2][0][RTW89_FCC][27] = 70,
- [2][0][RTW89_ETSI][27] = 54,
- [2][0][RTW89_MKK][27] = 70,
+ [2][0][RTW89_FCC][27] = 62,
+ [2][0][RTW89_ETSI][27] = 52,
+ [2][0][RTW89_MKK][27] = 74,
[2][0][RTW89_IC][27] = 127,
[2][0][RTW89_ACMA][27] = 127,
- [2][0][RTW89_FCC][29] = 70,
- [2][0][RTW89_ETSI][29] = 54,
- [2][0][RTW89_MKK][29] = 70,
+ [2][0][RTW89_FCC][29] = 62,
+ [2][0][RTW89_ETSI][29] = 52,
+ [2][0][RTW89_MKK][29] = 74,
[2][0][RTW89_IC][29] = 127,
[2][0][RTW89_ACMA][29] = 127,
- [2][0][RTW89_FCC][31] = 70,
- [2][0][RTW89_ETSI][31] = 54,
- [2][0][RTW89_MKK][31] = 70,
+ [2][0][RTW89_FCC][31] = 62,
+ [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] = 72,
- [2][0][RTW89_ETSI][33] = 54,
- [2][0][RTW89_MKK][33] = 70,
+ [2][0][RTW89_FCC][33] = 64,
+ [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] = 72,
- [2][0][RTW89_ETSI][35] = 54,
- [2][0][RTW89_MKK][35] = 70,
+ [2][0][RTW89_FCC][35] = 64,
+ [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] = 70,
+ [2][0][RTW89_FCC][37] = 62,
[2][0][RTW89_ETSI][37] = 127,
- [2][0][RTW89_MKK][37] = 66,
+ [2][0][RTW89_MKK][37] = 74,
[2][0][RTW89_IC][37] = 70,
[2][0][RTW89_ACMA][37] = 76,
- [2][0][RTW89_FCC][38] = 84,
- [2][0][RTW89_ETSI][38] = 30,
+ [2][0][RTW89_FCC][38] = 76,
+ [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] = 84,
- [2][0][RTW89_ETSI][40] = 30,
+ [2][0][RTW89_FCC][40] = 76,
+ [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_FCC][42] = 84,
- [2][0][RTW89_ETSI][42] = 30,
+ [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] = 84,
- [2][0][RTW89_ETSI][44] = 30,
+ [2][0][RTW89_FCC][44] = 76,
+ [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] = 84,
- [2][0][RTW89_ETSI][46] = 30,
+ [2][0][RTW89_FCC][46] = 76,
+ [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] = 56,
+ [2][0][RTW89_FCC][48] = 48,
[2][0][RTW89_ETSI][48] = 127,
[2][0][RTW89_MKK][48] = 127,
[2][0][RTW89_IC][48] = 127,
[2][0][RTW89_ACMA][48] = 127,
- [2][0][RTW89_FCC][50] = 56,
+ [2][0][RTW89_FCC][50] = 48,
[2][0][RTW89_ETSI][50] = 127,
[2][0][RTW89_MKK][50] = 127,
[2][0][RTW89_IC][50] = 127,
[2][0][RTW89_ACMA][50] = 127,
- [2][0][RTW89_FCC][52] = 56,
+ [2][0][RTW89_FCC][52] = 48,
[2][0][RTW89_ETSI][52] = 127,
[2][0][RTW89_MKK][52] = 127,
[2][0][RTW89_IC][52] = 127,
[2][0][RTW89_ACMA][52] = 127,
- [2][1][RTW89_FCC][0] = 50,
- [2][1][RTW89_ETSI][0] = 42,
- [2][1][RTW89_MKK][0] = 36,
+ [2][1][RTW89_FCC][0] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][2] = 42,
- [2][1][RTW89_MKK][2] = 36,
+ [2][1][RTW89_FCC][2] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][4] = 42,
+ [2][1][RTW89_FCC][4] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][6] = 42,
+ [2][1][RTW89_FCC][6] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][8] = 42,
- [2][1][RTW89_MKK][8] = 34,
+ [2][1][RTW89_FCC][8] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][10] = 42,
- [2][1][RTW89_MKK][10] = 34,
+ [2][1][RTW89_FCC][10] = 42,
+ [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] = 52,
- [2][1][RTW89_ETSI][12] = 42,
- [2][1][RTW89_MKK][12] = 36,
+ [2][1][RTW89_FCC][12] = 44,
+ [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] = 52,
- [2][1][RTW89_ETSI][14] = 42,
- [2][1][RTW89_MKK][14] = 36,
+ [2][1][RTW89_FCC][14] = 44,
+ [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] = 50,
- [2][1][RTW89_ETSI][15] = 42,
- [2][1][RTW89_MKK][15] = 54,
+ [2][1][RTW89_FCC][15] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][17] = 42,
- [2][1][RTW89_MKK][17] = 56,
+ [2][1][RTW89_FCC][17] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][19] = 42,
- [2][1][RTW89_MKK][19] = 56,
+ [2][1][RTW89_FCC][19] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][21] = 42,
- [2][1][RTW89_MKK][21] = 56,
+ [2][1][RTW89_FCC][21] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][23] = 42,
- [2][1][RTW89_MKK][23] = 56,
+ [2][1][RTW89_FCC][23] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][25] = 42,
- [2][1][RTW89_MKK][25] = 56,
+ [2][1][RTW89_FCC][25] = 42,
+ [2][1][RTW89_ETSI][25] = 40,
+ [2][1][RTW89_MKK][25] = 66,
[2][1][RTW89_IC][25] = 127,
[2][1][RTW89_ACMA][25] = 127,
- [2][1][RTW89_FCC][27] = 50,
- [2][1][RTW89_ETSI][27] = 42,
- [2][1][RTW89_MKK][27] = 56,
+ [2][1][RTW89_FCC][27] = 42,
+ [2][1][RTW89_ETSI][27] = 40,
+ [2][1][RTW89_MKK][27] = 66,
[2][1][RTW89_IC][27] = 127,
[2][1][RTW89_ACMA][27] = 127,
- [2][1][RTW89_FCC][29] = 50,
- [2][1][RTW89_ETSI][29] = 42,
- [2][1][RTW89_MKK][29] = 56,
+ [2][1][RTW89_FCC][29] = 42,
+ [2][1][RTW89_ETSI][29] = 40,
+ [2][1][RTW89_MKK][29] = 66,
[2][1][RTW89_IC][29] = 127,
[2][1][RTW89_ACMA][29] = 127,
- [2][1][RTW89_FCC][31] = 50,
- [2][1][RTW89_ETSI][31] = 42,
- [2][1][RTW89_MKK][31] = 56,
+ [2][1][RTW89_FCC][31] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][33] = 42,
- [2][1][RTW89_MKK][33] = 56,
+ [2][1][RTW89_FCC][33] = 42,
+ [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] = 50,
- [2][1][RTW89_ETSI][35] = 42,
- [2][1][RTW89_MKK][35] = 56,
+ [2][1][RTW89_FCC][35] = 42,
+ [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] = 50,
+ [2][1][RTW89_FCC][37] = 42,
[2][1][RTW89_ETSI][37] = 127,
- [2][1][RTW89_MKK][37] = 54,
+ [2][1][RTW89_MKK][37] = 66,
[2][1][RTW89_IC][37] = 50,
[2][1][RTW89_ACMA][37] = 60,
- [2][1][RTW89_FCC][38] = 84,
- [2][1][RTW89_ETSI][38] = 18,
+ [2][1][RTW89_FCC][38] = 76,
+ [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] = 84,
- [2][1][RTW89_ETSI][40] = 18,
+ [2][1][RTW89_FCC][40] = 76,
+ [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] = 84,
- [2][1][RTW89_ETSI][42] = 18,
+ [2][1][RTW89_FCC][42] = 76,
+ [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] = 84,
- [2][1][RTW89_ETSI][44] = 18,
+ [2][1][RTW89_FCC][44] = 76,
+ [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] = 84,
- [2][1][RTW89_ETSI][46] = 18,
+ [2][1][RTW89_FCC][46] = 76,
+ [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] = 44,
+ [2][1][RTW89_FCC][48] = 36,
[2][1][RTW89_ETSI][48] = 127,
[2][1][RTW89_MKK][48] = 127,
[2][1][RTW89_IC][48] = 127,
[2][1][RTW89_ACMA][48] = 127,
- [2][1][RTW89_FCC][50] = 44,
+ [2][1][RTW89_FCC][50] = 36,
[2][1][RTW89_ETSI][50] = 127,
[2][1][RTW89_MKK][50] = 127,
[2][1][RTW89_IC][50] = 127,
[2][1][RTW89_ACMA][50] = 127,
- [2][1][RTW89_FCC][52] = 44,
+ [2][1][RTW89_FCC][52] = 36,
[2][1][RTW89_ETSI][52] = 127,
[2][1][RTW89_MKK][52] = 127,
[2][1][RTW89_IC][52] = 127,
diff --git a/drivers/net/wireless/silabs/wfx/bh.c b/drivers/net/wireless/silabs/wfx/bh.c
index bcea9d5b119c..21dfdcf9cc27 100644
--- a/drivers/net/wireless/silabs/wfx/bh.c
+++ b/drivers/net/wireless/silabs/wfx/bh.c
@@ -267,7 +267,7 @@ void wfx_bh_request_rx(struct wfx_dev *wdev)
wfx_control_reg_read(wdev, &cur);
prev = atomic_xchg(&wdev->hif.ctrl_reg, cur);
complete(&wdev->hif.ctrl_ready);
- queue_work(system_highpri_wq, &wdev->hif.bh);
+ queue_work(wdev->bh_wq, &wdev->hif.bh);
if (!(cur & CTRL_NEXT_LEN_MASK))
dev_err(wdev->dev, "unexpected control register value: length field is 0: %04x\n",
@@ -280,7 +280,7 @@ void wfx_bh_request_rx(struct wfx_dev *wdev)
/* Driver want to send data */
void wfx_bh_request_tx(struct wfx_dev *wdev)
{
- queue_work(system_highpri_wq, &wdev->hif.bh);
+ queue_work(wdev->bh_wq, &wdev->hif.bh);
}
/* If IRQ is not available, this function allow to manually poll the control register and simulate
@@ -295,7 +295,7 @@ void wfx_bh_poll_irq(struct wfx_dev *wdev)
u32 reg;
WARN(!wdev->poll_irq, "unexpected IRQ polling can mask IRQ");
- flush_workqueue(system_highpri_wq);
+ flush_workqueue(wdev->bh_wq);
start = ktime_get();
for (;;) {
wfx_control_reg_read(wdev, &reg);
diff --git a/drivers/net/wireless/silabs/wfx/data_rx.c b/drivers/net/wireless/silabs/wfx/data_rx.c
index a4b5ffe158e4..e099a9e65bae 100644
--- a/drivers/net/wireless/silabs/wfx/data_rx.c
+++ b/drivers/net/wireless/silabs/wfx/data_rx.c
@@ -15,6 +15,7 @@
static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt)
{
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
int params, tid;
if (wfx_api_older_than(wvif->wdev, 3, 6))
@@ -24,12 +25,12 @@ static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt)
case WLAN_ACTION_ADDBA_REQ:
params = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
tid = (params & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
- ieee80211_start_rx_ba_session_offl(wvif->vif, mgmt->sa, tid);
+ ieee80211_start_rx_ba_session_offl(vif, mgmt->sa, tid);
break;
case WLAN_ACTION_DELBA:
params = le16_to_cpu(mgmt->u.action.u.delba.params);
tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
- ieee80211_stop_rx_ba_session_offl(wvif->vif, mgmt->sa, tid);
+ ieee80211_stop_rx_ba_session_offl(vif, mgmt->sa, tid);
break;
}
}
diff --git a/drivers/net/wireless/silabs/wfx/data_tx.c b/drivers/net/wireless/silabs/wfx/data_tx.c
index e07381b2ff4d..6a5e52a96d18 100644
--- a/drivers/net/wireless/silabs/wfx/data_tx.c
+++ b/drivers/net/wireless/silabs/wfx/data_tx.c
@@ -212,11 +212,12 @@ static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta,
struct ieee80211_hdr *hdr)
{
struct wfx_sta_priv *sta_priv = sta ? (struct wfx_sta_priv *)&sta->drv_priv : NULL;
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
const u8 *da = ieee80211_get_DA(hdr);
if (sta_priv && sta_priv->link_id)
return sta_priv->link_id;
- if (wvif->vif->type != NL80211_IFTYPE_AP)
+ if (vif->type != NL80211_IFTYPE_AP)
return 0;
if (is_multicast_ether_addr(da))
return 0;
diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.c b/drivers/net/wireless/silabs/wfx/hif_tx.c
index ae3cc5919dcd..2b92c227efbc 100644
--- a/drivers/net/wireless/silabs/wfx/hif_tx.c
+++ b/drivers/net/wireless/silabs/wfx/hif_tx.c
@@ -73,7 +73,7 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct wfx_hif_msg *request,
if (no_reply) {
/* Chip won't reply. Ensure the wq has send the buffer before to continue. */
- flush_workqueue(system_highpri_wq);
+ flush_workqueue(wdev->bh_wq);
ret = 0;
goto end;
}
diff --git a/drivers/net/wireless/silabs/wfx/key.c b/drivers/net/wireless/silabs/wfx/key.c
index 8f23e8d42bd4..196d64ef68f3 100644
--- a/drivers/net/wireless/silabs/wfx/key.c
+++ b/drivers/net/wireless/silabs/wfx/key.c
@@ -156,6 +156,7 @@ static int wfx_add_key(struct wfx_vif *wvif, struct ieee80211_sta *sta,
struct wfx_dev *wdev = wvif->wdev;
int idx = wfx_alloc_key(wvif->wdev);
bool pairwise = key->flags & IEEE80211_KEY_FLAG_PAIRWISE;
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
WARN(key->flags & IEEE80211_KEY_FLAG_PAIRWISE && !sta, "inconsistent data");
ieee80211_get_key_rx_seq(key, 0, &seq);
@@ -174,7 +175,7 @@ static int wfx_add_key(struct wfx_vif *wvif, struct ieee80211_sta *sta,
k.type = fill_tkip_pair(&k.key.tkip_pairwise_key, key, sta->addr);
else
k.type = fill_tkip_group(&k.key.tkip_group_key, key, &seq,
- wvif->vif->type);
+ vif->type);
} else if (key->cipher == WLAN_CIPHER_SUITE_CCMP) {
if (pairwise)
k.type = fill_ccmp_pair(&k.key.aes_pairwise_key, key, sta->addr);
@@ -224,4 +225,3 @@ int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_
mutex_unlock(&wvif->wdev->conf_mutex);
return ret;
}
-
diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c
index b93b16b900c8..bbfd3fa51921 100644
--- a/drivers/net/wireless/silabs/wfx/main.c
+++ b/drivers/net/wireless/silabs/wfx/main.c
@@ -345,6 +345,10 @@ int wfx_probe(struct wfx_dev *wdev)
wdev->pdata.gpio_wakeup = NULL;
wdev->poll_irq = true;
+ wdev->bh_wq = alloc_workqueue("wfx_bh_wq", WQ_HIGHPRI, 0);
+ if (!wdev->bh_wq)
+ return -ENOMEM;
+
wfx_bh_register(wdev);
err = wfx_init_device(wdev);
@@ -458,6 +462,7 @@ irq_unsubscribe:
wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv);
bh_unregister:
wfx_bh_unregister(wdev);
+ destroy_workqueue(wdev->bh_wq);
return err;
}
@@ -467,6 +472,7 @@ void wfx_release(struct wfx_dev *wdev)
wfx_hif_shutdown(wdev);
wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv);
wfx_bh_unregister(wdev);
+ destroy_workqueue(wdev->bh_wq);
}
static int __init wfx_core_init(void)
diff --git a/drivers/net/wireless/silabs/wfx/queue.c b/drivers/net/wireless/silabs/wfx/queue.c
index 729825230db2..37f492e5d3be 100644
--- a/drivers/net/wireless/silabs/wfx/queue.c
+++ b/drivers/net/wireless/silabs/wfx/queue.c
@@ -205,9 +205,10 @@ unsigned int wfx_pending_get_pkt_us_delay(struct wfx_dev *wdev, struct sk_buff *
bool wfx_tx_queues_has_cab(struct wfx_vif *wvif)
{
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
int i;
- if (wvif->vif->type != NL80211_IFTYPE_AP)
+ if (vif->type != NL80211_IFTYPE_AP)
return false;
for (i = 0; i < IEEE80211_NUM_ACS; ++i)
/* Note: since only AP can have mcast frames in queue and only one vif can be AP,
diff --git a/drivers/net/wireless/silabs/wfx/scan.c b/drivers/net/wireless/silabs/wfx/scan.c
index 7f34f0d322f9..16f619ed22e0 100644
--- a/drivers/net/wireless/silabs/wfx/scan.c
+++ b/drivers/net/wireless/silabs/wfx/scan.c
@@ -23,9 +23,11 @@ static void wfx_ieee80211_scan_completed_compat(struct ieee80211_hw *hw, bool ab
static int update_probe_tmpl(struct wfx_vif *wvif, struct cfg80211_scan_request *req)
{
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
struct sk_buff *skb;
- skb = ieee80211_probereq_get(wvif->wdev->hw, wvif->vif->addr, NULL, 0, req->ie_len);
+ skb = ieee80211_probereq_get(wvif->wdev->hw, vif->addr, NULL, 0,
+ req->ie_len);
if (!skb)
return -ENOMEM;
@@ -37,8 +39,9 @@ static int update_probe_tmpl(struct wfx_vif *wvif, struct cfg80211_scan_request
static int send_scan_req(struct wfx_vif *wvif, struct cfg80211_scan_request *req, int start_idx)
{
- int i, ret;
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
struct ieee80211_channel *ch_start, *ch_cur;
+ int i, ret;
for (i = start_idx; i < req->n_channels; i++) {
ch_start = req->channels[start_idx];
@@ -75,8 +78,8 @@ static int send_scan_req(struct wfx_vif *wvif, struct cfg80211_scan_request *req
} else {
ret = wvif->scan_nb_chan_done;
}
- if (req->channels[start_idx]->max_power != wvif->vif->bss_conf.txpower)
- wfx_hif_set_output_power(wvif, wvif->vif->bss_conf.txpower);
+ if (req->channels[start_idx]->max_power != vif->bss_conf.txpower)
+ wfx_hif_set_output_power(wvif, vif->bss_conf.txpower);
wfx_tx_unlock(wvif->wdev);
return ret;
}
diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c
index 3297d73c327a..e551fa284a43 100644
--- a/drivers/net/wireless/silabs/wfx/sta.c
+++ b/drivers/net/wireless/silabs/wfx/sta.c
@@ -98,9 +98,10 @@ static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
unsigned int *total_flags, u64 unused)
{
- struct wfx_vif *wvif = NULL;
- struct wfx_dev *wdev = hw->priv;
bool filter_bssid, filter_prbreq, filter_beacon;
+ struct ieee80211_vif *vif = NULL;
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = NULL;
/* Notes:
* - Probe responses (FIF_BCN_PRBRESP_PROMISC) are never filtered
@@ -131,8 +132,9 @@ void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
else
filter_bssid = true;
+ vif = wvif_to_vif(wvif);
/* In AP mode, chip can reply to probe request itself */
- if (*total_flags & FIF_PROBE_REQ && wvif->vif->type == NL80211_IFTYPE_AP) {
+ if (*total_flags & FIF_PROBE_REQ && vif->type == NL80211_IFTYPE_AP) {
dev_dbg(wdev->dev, "do not forward probe request in AP mode\n");
*total_flags &= ~FIF_PROBE_REQ;
}
@@ -152,19 +154,28 @@ static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps)
{
struct ieee80211_channel *chan0 = NULL, *chan1 = NULL;
struct ieee80211_conf *conf = &wvif->wdev->hw->conf;
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
- WARN(!wvif->vif->bss_conf.assoc && enable_ps,
+ WARN(!vif->bss_conf.assoc && enable_ps,
"enable_ps is reliable only if associated");
- if (wdev_to_wvif(wvif->wdev, 0))
- chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan;
- if (wdev_to_wvif(wvif->wdev, 1))
- chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan;
- if (chan0 && chan1 && wvif->vif->type != NL80211_IFTYPE_AP) {
+ if (wdev_to_wvif(wvif->wdev, 0)) {
+ struct wfx_vif *wvif_ch0 = wdev_to_wvif(wvif->wdev, 0);
+ struct ieee80211_vif *vif_ch0 = wvif_to_vif(wvif_ch0);
+
+ chan0 = vif_ch0->bss_conf.chandef.chan;
+ }
+ if (wdev_to_wvif(wvif->wdev, 1)) {
+ struct wfx_vif *wvif_ch1 = wdev_to_wvif(wvif->wdev, 1);
+ struct ieee80211_vif *vif_ch1 = wvif_to_vif(wvif_ch1);
+
+ chan1 = vif_ch1->bss_conf.chandef.chan;
+ }
+ if (chan0 && chan1 && vif->type != NL80211_IFTYPE_AP) {
if (chan0->hw_value == chan1->hw_value) {
/* It is useless to enable PS if channels are the same. */
if (enable_ps)
*enable_ps = false;
- if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps)
+ if (vif->bss_conf.assoc && vif->bss_conf.ps)
dev_info(wvif->wdev->dev, "ignoring requested PS mode");
return -1;
}
@@ -177,8 +188,8 @@ static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps)
return 30;
}
if (enable_ps)
- *enable_ps = wvif->vif->bss_conf.ps;
- if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps)
+ *enable_ps = vif->bss_conf.ps;
+ if (vif->bss_conf.assoc && vif->bss_conf.ps)
return conf->dynamic_ps_timeout;
else
return -1;
@@ -186,10 +197,11 @@ static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps)
int wfx_update_pm(struct wfx_vif *wvif)
{
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
int ps_timeout;
bool ps;
- if (!wvif->vif->bss_conf.assoc)
+ if (!vif->bss_conf.assoc)
return 0;
ps_timeout = wfx_get_ps_timeout(wvif, &ps);
if (!ps)
@@ -215,7 +227,8 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_lock(&wdev->conf_mutex);
assign_bit(queue, &wvif->uapsd_mask, params->uapsd);
wfx_hif_set_edca_queue_params(wvif, queue, params);
- if (wvif->vif->type == NL80211_IFTYPE_STATION && old_uapsd != wvif->uapsd_mask) {
+ if (vif->type == NL80211_IFTYPE_STATION &&
+ old_uapsd != wvif->uapsd_mask) {
wfx_hif_set_uapsd_info(wvif, wvif->uapsd_mask);
wfx_update_pm(wvif);
}
@@ -238,24 +251,26 @@ void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
/* RSSI: signed Q8.0, RCPI: unsigned Q7.1
* RSSI = RCPI / 2 - 110
*/
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
int rcpi_rssi;
int cqm_evt;
rcpi_rssi = raw_rcpi_rssi / 2 - 110;
- if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold)
+ if (rcpi_rssi <= vif->bss_conf.cqm_rssi_thold)
cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
else
cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
- ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
+ ieee80211_cqm_rssi_notify(vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
}
static void wfx_beacon_loss_work(struct work_struct *work)
{
struct wfx_vif *wvif = container_of(to_delayed_work(work), struct wfx_vif,
beacon_loss_work);
- struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf;
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
- ieee80211_beacon_loss(wvif->vif);
+ ieee80211_beacon_loss(vif);
schedule_delayed_work(to_delayed_work(work), msecs_to_jiffies(bss_conf->beacon_int));
}
@@ -321,15 +336,16 @@ int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ie
static int wfx_upload_ap_templates(struct wfx_vif *wvif)
{
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
struct sk_buff *skb;
- skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
+ skb = ieee80211_beacon_get(wvif->wdev->hw, vif);
if (!skb)
return -ENOMEM;
wfx_hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN, API_RATE_INDEX_B_1MBPS);
dev_kfree_skb(skb);
- skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif);
+ skb = ieee80211_proberesp_get(wvif->wdev->hw, vif);
if (!skb)
return -ENOMEM;
wfx_hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES, API_RATE_INDEX_B_1MBPS);
@@ -339,7 +355,8 @@ static int wfx_upload_ap_templates(struct wfx_vif *wvif)
static void wfx_set_mfp_ap(struct wfx_vif *wvif)
{
- struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
+ struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, vif);
const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, skb->data + ieoffset,
skb->len - ieoffset);
@@ -388,12 +405,13 @@ void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
static void wfx_join(struct wfx_vif *wvif)
{
- int ret;
- struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
+ struct ieee80211_bss_conf *conf = &vif->bss_conf;
struct cfg80211_bss *bss = NULL;
u8 ssid[IEEE80211_MAX_SSID_LEN];
const u8 *ssidie = NULL;
int ssidlen = 0;
+ int ret;
wfx_tx_lock_flush(wvif->wdev);
@@ -420,7 +438,7 @@ static void wfx_join(struct wfx_vif *wvif)
wvif->join_in_progress = true;
ret = wfx_hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
if (ret) {
- ieee80211_connection_loss(wvif->vif);
+ ieee80211_connection_loss(vif);
wfx_reset(wvif);
} else {
/* Due to beacon filtering it is possible that the AP's beacon is not known for the
@@ -434,13 +452,14 @@ static void wfx_join(struct wfx_vif *wvif)
static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_bss_conf *info)
{
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
struct ieee80211_sta *sta = NULL;
int ampdu_density = 0;
bool greenfield = false;
rcu_read_lock(); /* protect sta */
if (info->bssid && !info->ibss_joined)
- sta = ieee80211_find_sta(wvif->vif, info->bssid);
+ sta = ieee80211_find_sta(vif, info->bssid);
if (sta && sta->deflink.ht_cap.ht_supported)
ampdu_density = sta->deflink.ht_cap.ampdu_density;
if (sta && sta->deflink.ht_cap.ht_supported &&
@@ -561,11 +580,13 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
static int wfx_update_tim(struct wfx_vif *wvif)
{
+ struct ieee80211_vif *vif = wvif_to_vif(wvif);
struct sk_buff *skb;
u16 tim_offset, tim_length;
u8 *tim_ptr;
- skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif, &tim_offset, &tim_length);
+ skb = ieee80211_beacon_get_tim(wvif->wdev->hw, vif, &tim_offset,
+ &tim_length);
if (!skb)
return -ENOENT;
tim_ptr = skb->data + tim_offset;
@@ -707,8 +728,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
return -EOPNOTSUPP;
}
- /* FIXME: prefer use of container_of() to get vif */
- wvif->vif = vif;
wvif->wdev = wdev;
wvif->link_id_map = 1; /* link-id 0 is reserved for multicast */
@@ -767,7 +786,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
cancel_delayed_work_sync(&wvif->beacon_loss_work);
wdev->vif[wvif->id] = NULL;
- wvif->vif = NULL;
mutex_unlock(&wdev->conf_mutex);
diff --git a/drivers/net/wireless/silabs/wfx/wfx.h b/drivers/net/wireless/silabs/wfx/wfx.h
index 6594cc647c2f..13ba84b3b2c3 100644
--- a/drivers/net/wireless/silabs/wfx/wfx.h
+++ b/drivers/net/wireless/silabs/wfx/wfx.h
@@ -57,11 +57,11 @@ struct wfx_dev {
struct mutex rx_stats_lock;
struct wfx_hif_tx_power_loop_info tx_power_loop_info;
struct mutex tx_power_loop_info_lock;
+ struct workqueue_struct *bh_wq;
};
struct wfx_vif {
struct wfx_dev *wdev;
- struct ieee80211_vif *vif;
struct ieee80211_channel *channel;
int id;
@@ -91,6 +91,11 @@ struct wfx_vif {
struct completion set_pm_mode_complete;
};
+static inline struct ieee80211_vif *wvif_to_vif(struct wfx_vif *wvif)
+{
+ return container_of((void *)wvif, struct ieee80211_vif, drv_priv);
+}
+
static inline struct wfx_vif *wdev_to_wvif(struct wfx_dev *wdev, int vif_id)
{
if (vif_id >= ARRAY_SIZE(wdev->vif)) {
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index e6d426edab56..e945aafd88ee 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -169,11 +169,9 @@ int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms)
msleep(1);
/* read from both event fields */
- wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector,
- sizeof(events_vector));
+ events_vector = wl1251_mem_read32(wl, wl->mbox_ptr[0]);
event = events_vector & mask;
- wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector,
- sizeof(events_vector));
+ events_vector = wl1251_mem_read32(wl, wl->mbox_ptr[1]);
event |= events_vector & mask;
} while (!event);
@@ -202,7 +200,7 @@ void wl1251_event_mbox_config(struct wl1251 *wl)
int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
{
- struct event_mailbox mbox;
+ struct event_mailbox *mbox;
int ret;
wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
@@ -210,12 +208,20 @@ int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
if (mbox_num > 1)
return -EINVAL;
+ mbox = kmalloc(sizeof(*mbox), GFP_KERNEL);
+ if (!mbox) {
+ wl1251_error("can not allocate mbox buffer");
+ return -ENOMEM;
+ }
+
/* first we read the mbox descriptor */
- wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
- sizeof(struct event_mailbox));
+ wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], mbox,
+ sizeof(*mbox));
/* process the descriptor */
- ret = wl1251_event_process(wl, &mbox);
+ ret = wl1251_event_process(wl, mbox);
+ kfree(mbox);
+
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/ti/wl1251/io.c b/drivers/net/wireless/ti/wl1251/io.c
index 5ebe7958ed5c..e8d567af74b4 100644
--- a/drivers/net/wireless/ti/wl1251/io.c
+++ b/drivers/net/wireless/ti/wl1251/io.c
@@ -121,7 +121,13 @@ void wl1251_set_partition(struct wl1251 *wl,
u32 mem_start, u32 mem_size,
u32 reg_start, u32 reg_size)
{
- struct wl1251_partition partition[2];
+ struct wl1251_partition_set *partition;
+
+ partition = kmalloc(sizeof(*partition), GFP_KERNEL);
+ if (!partition) {
+ wl1251_error("can not allocate partition buffer");
+ return;
+ }
wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
mem_start, mem_size);
@@ -164,10 +170,10 @@ void wl1251_set_partition(struct wl1251 *wl,
reg_start, reg_size);
}
- partition[0].start = mem_start;
- partition[0].size = mem_size;
- partition[1].start = reg_start;
- partition[1].size = reg_size;
+ partition->mem.start = mem_start;
+ partition->mem.size = mem_size;
+ partition->reg.start = reg_start;
+ partition->reg.size = reg_size;
wl->physical_mem_addr = mem_start;
wl->physical_reg_addr = reg_start;
@@ -176,5 +182,7 @@ void wl1251_set_partition(struct wl1251 *wl,
wl->virtual_reg_addr = mem_size;
wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition,
- sizeof(partition));
+ sizeof(*partition));
+
+ kfree(partition);
}
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
index 98cd39619d57..e9dc3c72bb11 100644
--- a/drivers/net/wireless/ti/wl1251/tx.c
+++ b/drivers/net/wireless/ti/wl1251/tx.c
@@ -443,19 +443,25 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
void wl1251_tx_complete(struct wl1251 *wl)
{
int i, result_index, num_complete = 0, queue_len;
- struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
+ struct tx_result *result, *result_ptr;
unsigned long flags;
if (unlikely(wl->state != WL1251_STATE_ON))
return;
+ result = kmalloc_array(FW_TX_CMPLT_BLOCK_SIZE, sizeof(*result), GFP_KERNEL);
+ if (!result) {
+ wl1251_error("can not allocate result buffer");
+ return;
+ }
+
/* First we read the result */
- wl1251_mem_read(wl, wl->data_path->tx_complete_addr,
- result, sizeof(result));
+ wl1251_mem_read(wl, wl->data_path->tx_complete_addr, result,
+ FW_TX_CMPLT_BLOCK_SIZE * sizeof(*result));
result_index = wl->next_tx_complete;
- for (i = 0; i < ARRAY_SIZE(result); i++) {
+ for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) {
result_ptr = &result[result_index];
if (result_ptr->done_1 == 1 &&
@@ -538,6 +544,7 @@ void wl1251_tx_complete(struct wl1251 *wl)
}
+ kfree(result);
wl->next_tx_complete = result_index;
}
diff --git a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
index c6b032f95d2e..4627847c6daa 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c
@@ -372,8 +372,6 @@ bool ipc_protocol_dl_td_prepare(struct iosm_protocol *ipc_protocol,
struct sk_buff *ipc_protocol_dl_td_process(struct iosm_protocol *ipc_protocol,
struct ipc_pipe *pipe)
{
- u32 tail =
- le32_to_cpu(ipc_protocol->p_ap_shm->tail_array[pipe->pipe_nr]);
struct ipc_protocol_td *p_td;
struct sk_buff *skb;
@@ -403,14 +401,6 @@ struct sk_buff *ipc_protocol_dl_td_process(struct iosm_protocol *ipc_protocol,
goto ret;
}
- if (!IPC_CB(skb)) {
- dev_err(ipc_protocol->dev, "pipe# %d, tail: %d skb_cb is NULL",
- pipe->pipe_nr, tail);
- ipc_pcie_kfree_skb(ipc_protocol->pcie, skb);
- skb = NULL;
- goto ret;
- }
-
if (p_td->buffer.address != IPC_CB(skb)->mapping) {
dev_err(ipc_protocol->dev, "invalid buf=%llx or skb=%p",
(unsigned long long)p_td->buffer.address, skb->data);
diff --git a/drivers/net/wwan/t7xx/t7xx_dpmaif.c b/drivers/net/wwan/t7xx/t7xx_dpmaif.c
index c8bf6929af51..6d3edadecbec 100644
--- a/drivers/net/wwan/t7xx/t7xx_dpmaif.c
+++ b/drivers/net/wwan/t7xx/t7xx_dpmaif.c
@@ -1043,15 +1043,13 @@ unsigned int t7xx_dpmaif_dl_dlq_pit_get_wr_idx(struct dpmaif_hw_info *hw_info,
return value & DPMAIF_DL_RD_WR_IDX_MSK;
}
-static bool t7xx_dl_add_timedout(struct dpmaif_hw_info *hw_info)
+static int t7xx_dl_add_timedout(struct dpmaif_hw_info *hw_info)
{
u32 value;
- int ret;
- ret = ioread32_poll_timeout_atomic(hw_info->pcie_base + DPMAIF_DL_BAT_ADD,
+ return ioread32_poll_timeout_atomic(hw_info->pcie_base + DPMAIF_DL_BAT_ADD,
value, !(value & DPMAIF_DL_ADD_NOT_READY), 0,
DPMAIF_CHECK_TIMEOUT_US);
- return ret;
}
int t7xx_dpmaif_dl_snd_hw_bat_cnt(struct dpmaif_hw_info *hw_info, unsigned int bat_entry_cnt)
diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
index 46066dcd2607..0c52801ed0de 100644
--- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
+++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
@@ -97,8 +97,7 @@ static int t7xx_cldma_alloc_and_map_skb(struct cldma_ctrl *md_ctrl, struct cldma
if (!req->skb)
return -ENOMEM;
- req->mapped_buff = dma_map_single(md_ctrl->dev, req->skb->data,
- skb_data_area_size(req->skb), DMA_FROM_DEVICE);
+ req->mapped_buff = dma_map_single(md_ctrl->dev, req->skb->data, size, DMA_FROM_DEVICE);
if (dma_mapping_error(md_ctrl->dev, req->mapped_buff)) {
dev_kfree_skb_any(req->skb);
req->skb = NULL;
@@ -154,7 +153,7 @@ static int t7xx_cldma_gpd_rx_from_q(struct cldma_queue *queue, int budget, bool
if (req->mapped_buff) {
dma_unmap_single(md_ctrl->dev, req->mapped_buff,
- skb_data_area_size(skb), DMA_FROM_DEVICE);
+ queue->tr_ring->pkt_size, DMA_FROM_DEVICE);
req->mapped_buff = 0;
}
@@ -376,7 +375,7 @@ static void t7xx_cldma_ring_free(struct cldma_ctrl *md_ctrl,
list_for_each_entry_safe(req_cur, req_next, &ring->gpd_ring, entry) {
if (req_cur->mapped_buff && req_cur->skb) {
dma_unmap_single(md_ctrl->dev, req_cur->mapped_buff,
- skb_data_area_size(req_cur->skb), tx_rx);
+ ring->pkt_size, tx_rx);
req_cur->mapped_buff = 0;
}
diff --git a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
index 35a8a0d7c1ee..91a0eb19e0d8 100644
--- a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
+++ b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
@@ -151,14 +151,12 @@ static bool t7xx_alloc_and_map_skb_info(const struct dpmaif_ctrl *dpmaif_ctrl,
{
dma_addr_t data_bus_addr;
struct sk_buff *skb;
- size_t data_len;
skb = __dev_alloc_skb(size, GFP_KERNEL);
if (!skb)
return false;
- data_len = skb_data_area_size(skb);
- data_bus_addr = dma_map_single(dpmaif_ctrl->dev, skb->data, data_len, DMA_FROM_DEVICE);
+ data_bus_addr = dma_map_single(dpmaif_ctrl->dev, skb->data, size, DMA_FROM_DEVICE);
if (dma_mapping_error(dpmaif_ctrl->dev, data_bus_addr)) {
dev_err_ratelimited(dpmaif_ctrl->dev, "DMA mapping error\n");
dev_kfree_skb_any(skb);
@@ -167,7 +165,7 @@ static bool t7xx_alloc_and_map_skb_info(const struct dpmaif_ctrl *dpmaif_ctrl,
cur_skb->skb = skb;
cur_skb->data_bus_addr = data_bus_addr;
- cur_skb->data_len = data_len;
+ cur_skb->data_len = size;
return true;
}
diff --git a/drivers/net/wwan/t7xx/t7xx_modem_ops.c b/drivers/net/wwan/t7xx/t7xx_modem_ops.c
index 1056ad9bf34f..3458af31e864 100644
--- a/drivers/net/wwan/t7xx/t7xx_modem_ops.c
+++ b/drivers/net/wwan/t7xx/t7xx_modem_ops.c
@@ -458,9 +458,9 @@ static void t7xx_core_hk_handler(struct t7xx_modem *md, struct t7xx_fsm_ctl *ctl
enum t7xx_fsm_event_state event_id,
enum t7xx_fsm_event_state err_detect)
{
+ struct t7xx_fsm_event *event = NULL, *event_next;
struct t7xx_sys_info *core_info = &md->core_md;
struct device *dev = &md->t7xx_dev->pdev->dev;
- struct t7xx_fsm_event *event, *event_next;
unsigned long flags;
int ret;
@@ -493,7 +493,7 @@ static void t7xx_core_hk_handler(struct t7xx_modem *md, struct t7xx_fsm_ctl *ctl
goto err_free_event;
}
- if (ctl->exp_flg)
+ if (!event || ctl->exp_flg)
goto err_free_event;
ret = t7xx_parse_host_rt_data(ctl, core_info, dev, event->data, event->length);
diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c
index 5f1bb8d6afb6..871f2a27a398 100644
--- a/drivers/net/wwan/t7xx/t7xx_pci.c
+++ b/drivers/net/wwan/t7xx/t7xx_pci.c
@@ -568,7 +568,7 @@ static const struct dev_pm_ops t7xx_pci_pm_ops = {
static int t7xx_request_irq(struct pci_dev *pdev)
{
struct t7xx_pci_dev *t7xx_dev;
- int ret, i;
+ int ret = 0, i;
t7xx_dev = pci_get_drvdata(pdev);
diff --git a/drivers/net/wwan/t7xx/t7xx_port_proxy.c b/drivers/net/wwan/t7xx/t7xx_port_proxy.c
index 7d2c0e81e33d..d4de047ff0d4 100644
--- a/drivers/net/wwan/t7xx/t7xx_port_proxy.c
+++ b/drivers/net/wwan/t7xx/t7xx_port_proxy.c
@@ -350,9 +350,6 @@ static int t7xx_port_proxy_recv_skb(struct cldma_queue *queue, struct sk_buff *s
u16 seq_num, channel;
int ret;
- if (!skb)
- return -EINVAL;
-
channel = FIELD_GET(CCCI_H_CHN_FLD, le32_to_cpu(ccci_h->status));
if (t7xx_fsm_get_md_state(ctl) == MD_STATE_INVALID) {
dev_err_ratelimited(dev, "Packet drop on channel 0x%x, modem not ready\n", channel);
diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c
index a491db46e3bd..d9f6367b9993 100644
--- a/drivers/nfc/pn533/pn533.c
+++ b/drivers/nfc/pn533/pn533.c
@@ -2787,13 +2787,14 @@ void pn53x_common_clean(struct pn533 *priv)
{
struct pn533_cmd *cmd, *n;
+ /* delete the timer before cleanup the worker */
+ del_timer_sync(&priv->listen_timer);
+
flush_delayed_work(&priv->poll_work);
destroy_workqueue(priv->wq);
skb_queue_purge(&priv->resp_q);
- del_timer(&priv->listen_timer);
-
list_for_each_entry_safe(cmd, n, &priv->cmd_queue, queue) {
list_del(&cmd->queue);
kfree(cmd);
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index 6ab90891801d..816028c0f6ed 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -1550,6 +1550,11 @@ static const struct qcom_pcie_cfg sc7280_cfg = {
.pipe_clk_need_muxing = true,
};
+static const struct qcom_pcie_cfg sc8180x_cfg = {
+ .ops = &ops_1_9_0,
+ .has_tbu_clk = true,
+};
+
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = qcom_pcie_link_up,
.start_link = qcom_pcie_start_link,
@@ -1656,7 +1661,7 @@ static const struct of_device_id qcom_pcie_match[] = {
{ .compatible = "qcom,pcie-qcs404", .data = &ipq4019_cfg },
{ .compatible = "qcom,pcie-sdm845", .data = &sdm845_cfg },
{ .compatible = "qcom,pcie-sm8250", .data = &sm8250_cfg },
- { .compatible = "qcom,pcie-sc8180x", .data = &sm8250_cfg },
+ { .compatible = "qcom,pcie-sc8180x", .data = &sc8180x_cfg },
{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &sm8450_pcie0_cfg },
{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &sm8450_pcie1_cfg },
{ .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg },
diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
index 09d9bf465d72..ffec82c8a523 100644
--- a/drivers/pci/controller/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
@@ -272,7 +272,6 @@ struct advk_pcie {
u32 actions;
} wins[OB_WIN_COUNT];
u8 wins_count;
- int irq;
struct irq_domain *rp_irq_domain;
struct irq_domain *irq_domain;
struct irq_chip irq_chip;
@@ -1570,26 +1569,21 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
}
}
-static void advk_pcie_irq_handler(struct irq_desc *desc)
+static irqreturn_t advk_pcie_irq_handler(int irq, void *arg)
{
- struct advk_pcie *pcie = irq_desc_get_handler_data(desc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
- u32 val, mask, status;
+ struct advk_pcie *pcie = arg;
+ u32 status;
- chained_irq_enter(chip, desc);
+ status = advk_readl(pcie, HOST_CTRL_INT_STATUS_REG);
+ if (!(status & PCIE_IRQ_CORE_INT))
+ return IRQ_NONE;
- val = advk_readl(pcie, HOST_CTRL_INT_STATUS_REG);
- mask = advk_readl(pcie, HOST_CTRL_INT_MASK_REG);
- status = val & ((~mask) & PCIE_IRQ_ALL_MASK);
+ advk_pcie_handle_int(pcie);
- if (status & PCIE_IRQ_CORE_INT) {
- advk_pcie_handle_int(pcie);
+ /* Clear interrupt */
+ advk_writel(pcie, PCIE_IRQ_CORE_INT, HOST_CTRL_INT_STATUS_REG);
- /* Clear interrupt */
- advk_writel(pcie, PCIE_IRQ_CORE_INT, HOST_CTRL_INT_STATUS_REG);
- }
-
- chained_irq_exit(chip, desc);
+ return IRQ_HANDLED;
}
static int advk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
@@ -1669,7 +1663,7 @@ static int advk_pcie_probe(struct platform_device *pdev)
struct advk_pcie *pcie;
struct pci_host_bridge *bridge;
struct resource_entry *entry;
- int ret;
+ int ret, irq;
bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie));
if (!bridge)
@@ -1755,9 +1749,17 @@ static int advk_pcie_probe(struct platform_device *pdev)
if (IS_ERR(pcie->base))
return PTR_ERR(pcie->base);
- pcie->irq = platform_get_irq(pdev, 0);
- if (pcie->irq < 0)
- return pcie->irq;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_irq(dev, irq, advk_pcie_irq_handler,
+ IRQF_SHARED | IRQF_NO_THREAD, "advk-pcie",
+ pcie);
+ if (ret) {
+ dev_err(dev, "Failed to register interrupt\n");
+ return ret;
+ }
pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node,
"reset-gpios", 0,
@@ -1814,15 +1816,12 @@ static int advk_pcie_probe(struct platform_device *pdev)
return ret;
}
- irq_set_chained_handler_and_data(pcie->irq, advk_pcie_irq_handler, pcie);
-
bridge->sysdata = pcie;
bridge->ops = &advk_pcie_ops;
bridge->map_irq = advk_pcie_map_irq;
ret = pci_host_probe(bridge);
if (ret < 0) {
- irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
advk_pcie_remove_rp_irq_domain(pcie);
advk_pcie_remove_msi_irq_domain(pcie);
advk_pcie_remove_irq_domain(pcie);
@@ -1871,9 +1870,6 @@ static int advk_pcie_remove(struct platform_device *pdev)
advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
- /* Remove IRQ handler */
- irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
-
/* Remove IRQ domains */
advk_pcie_remove_rp_irq_domain(pcie);
advk_pcie_remove_msi_irq_domain(pcie);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 9ecce435fb3f..d25122fbe98a 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2920,6 +2920,16 @@ static const struct dmi_system_id bridge_d3_blacklist[] = {
DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
DMI_MATCH(DMI_BOARD_NAME, "X299 DESIGNARE EX-CF"),
},
+ /*
+ * Downstream device is not accessible after putting a root port
+ * into D3cold and back into D0 on Elo i2.
+ */
+ .ident = "Elo i2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"),
+ },
},
#endif
{ }
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
index a3fa03bcd9a3..80838dc54b3a 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
@@ -1236,18 +1236,17 @@ FUNC_GROUP_DECL(SALT8, AA12);
FUNC_GROUP_DECL(WDTRST4, AA12);
#define AE12 196
-SIG_EXPR_LIST_DECL_SEMG(AE12, FWSPIDQ2, FWQSPID, FWSPID,
- SIG_DESC_SET(SCU438, 4));
+SIG_EXPR_LIST_DECL_SESG(AE12, FWSPIQ2, FWQSPI, SIG_DESC_SET(SCU438, 4));
SIG_EXPR_LIST_DECL_SESG(AE12, GPIOY4, GPIOY4);
-PIN_DECL_(AE12, SIG_EXPR_LIST_PTR(AE12, FWSPIDQ2),
+PIN_DECL_(AE12, SIG_EXPR_LIST_PTR(AE12, FWSPIQ2),
SIG_EXPR_LIST_PTR(AE12, GPIOY4));
#define AF12 197
-SIG_EXPR_LIST_DECL_SEMG(AF12, FWSPIDQ3, FWQSPID, FWSPID,
- SIG_DESC_SET(SCU438, 5));
+SIG_EXPR_LIST_DECL_SESG(AF12, FWSPIQ3, FWQSPI, SIG_DESC_SET(SCU438, 5));
SIG_EXPR_LIST_DECL_SESG(AF12, GPIOY5, GPIOY5);
-PIN_DECL_(AF12, SIG_EXPR_LIST_PTR(AF12, FWSPIDQ3),
+PIN_DECL_(AF12, SIG_EXPR_LIST_PTR(AF12, FWSPIQ3),
SIG_EXPR_LIST_PTR(AF12, GPIOY5));
+FUNC_GROUP_DECL(FWQSPI, AE12, AF12);
#define AC12 198
SSSF_PIN_DECL(AC12, GPIOY6, FWSPIABR, SIG_DESC_SET(SCU438, 6));
@@ -1520,9 +1519,8 @@ SIG_EXPR_LIST_DECL_SEMG(Y4, EMMCDAT7, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 3));
PIN_DECL_3(Y4, GPIO18E3, FWSPIDMISO, VBMISO, EMMCDAT7);
GROUP_DECL(FWSPID, Y1, Y2, Y3, Y4);
-GROUP_DECL(FWQSPID, Y1, Y2, Y3, Y4, AE12, AF12);
GROUP_DECL(EMMCG8, AB4, AA4, AC4, AA5, Y5, AB5, AB6, AC5, Y1, Y2, Y3, Y4);
-FUNC_DECL_2(FWSPID, FWSPID, FWQSPID);
+FUNC_DECL_1(FWSPID, FWSPID);
FUNC_GROUP_DECL(VB, Y1, Y2, Y3, Y4);
FUNC_DECL_3(EMMC, EMMCG1, EMMCG4, EMMCG8);
/*
@@ -1918,7 +1916,7 @@ static const struct aspeed_pin_group aspeed_g6_groups[] = {
ASPEED_PINCTRL_GROUP(FSI2),
ASPEED_PINCTRL_GROUP(FWSPIABR),
ASPEED_PINCTRL_GROUP(FWSPID),
- ASPEED_PINCTRL_GROUP(FWQSPID),
+ ASPEED_PINCTRL_GROUP(FWQSPI),
ASPEED_PINCTRL_GROUP(FWSPIWP),
ASPEED_PINCTRL_GROUP(GPIT0),
ASPEED_PINCTRL_GROUP(GPIT1),
@@ -2160,6 +2158,7 @@ static const struct aspeed_pin_function aspeed_g6_functions[] = {
ASPEED_PINCTRL_FUNC(FSI2),
ASPEED_PINCTRL_FUNC(FWSPIABR),
ASPEED_PINCTRL_FUNC(FWSPID),
+ ASPEED_PINCTRL_FUNC(FWQSPI),
ASPEED_PINCTRL_FUNC(FWSPIWP),
ASPEED_PINCTRL_FUNC(GPIT0),
ASPEED_PINCTRL_FUNC(GPIT1),
diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c
index 08e429a06922..cb258e1448d5 100644
--- a/drivers/ptp/ptp_clockmatrix.c
+++ b/drivers/ptp/ptp_clockmatrix.c
@@ -239,73 +239,97 @@ static int wait_for_boot_status_ready(struct idtcm *idtcm)
return -EBUSY;
}
-static int _idtcm_set_scsr_read_trig(struct idtcm_channel *channel,
- enum scsr_read_trig_sel trig, u8 ref)
+static int arm_tod_read_trig_sel_refclk(struct idtcm_channel *channel, u8 ref)
{
struct idtcm *idtcm = channel->idtcm;
- u16 tod_read_cmd = IDTCM_FW_REG(idtcm->fw_ver, V520, TOD_READ_PRIMARY_CMD);
- u8 val;
+ u16 tod_read_cmd = IDTCM_FW_REG(idtcm->fw_ver, V520, TOD_READ_SECONDARY_CMD);
+ u8 val = 0;
int err;
- if (trig == SCSR_TOD_READ_TRIG_SEL_REFCLK) {
- err = idtcm_read(idtcm, channel->tod_read_primary,
- TOD_READ_PRIMARY_SEL_CFG_0, &val, sizeof(val));
- if (err)
- return err;
-
- val &= ~(WR_REF_INDEX_MASK << WR_REF_INDEX_SHIFT);
- val |= (ref << WR_REF_INDEX_SHIFT);
-
- err = idtcm_write(idtcm, channel->tod_read_primary,
- TOD_READ_PRIMARY_SEL_CFG_0, &val, sizeof(val));
- if (err)
- return err;
- }
+ val &= ~(WR_REF_INDEX_MASK << WR_REF_INDEX_SHIFT);
+ val |= (ref << WR_REF_INDEX_SHIFT);
- err = idtcm_read(idtcm, channel->tod_read_primary,
- tod_read_cmd, &val, sizeof(val));
+ err = idtcm_write(idtcm, channel->tod_read_secondary,
+ TOD_READ_SECONDARY_SEL_CFG_0, &val, sizeof(val));
if (err)
return err;
- val &= ~(TOD_READ_TRIGGER_MASK << TOD_READ_TRIGGER_SHIFT);
- val |= (trig << TOD_READ_TRIGGER_SHIFT);
- val &= ~TOD_READ_TRIGGER_MODE; /* single shot */
+ val = 0 | (SCSR_TOD_READ_TRIG_SEL_REFCLK << TOD_READ_TRIGGER_SHIFT);
+
+ err = idtcm_write(idtcm, channel->tod_read_secondary, tod_read_cmd,
+ &val, sizeof(val));
+ if (err)
+ dev_err(idtcm->dev, "%s: err = %d", __func__, err);
- err = idtcm_write(idtcm, channel->tod_read_primary,
- tod_read_cmd, &val, sizeof(val));
return err;
}
-static int idtcm_enable_extts(struct idtcm_channel *channel, u8 todn, u8 ref,
- bool enable)
+static bool is_single_shot(u8 mask)
{
- struct idtcm *idtcm = channel->idtcm;
- u8 old_mask = idtcm->extts_mask;
- u8 mask = 1 << todn;
+ /* Treat single bit ToD masks as continuous trigger */
+ return mask <= 8 && is_power_of_2(mask);
+}
+
+static int idtcm_extts_enable(struct idtcm_channel *channel,
+ struct ptp_clock_request *rq, int on)
+{
+ u8 index = rq->extts.index;
+ struct idtcm *idtcm;
+ u8 mask = 1 << index;
int err = 0;
+ u8 old_mask;
+ int ref;
- if (todn >= MAX_TOD)
+ idtcm = channel->idtcm;
+ old_mask = idtcm->extts_mask;
+
+ /* Reject requests with unsupported flags */
+ if (rq->extts.flags & ~(PTP_ENABLE_FEATURE |
+ PTP_RISING_EDGE |
+ PTP_FALLING_EDGE |
+ PTP_STRICT_FLAGS))
+ return -EOPNOTSUPP;
+
+ /* Reject requests to enable time stamping on falling edge */
+ if ((rq->extts.flags & PTP_ENABLE_FEATURE) &&
+ (rq->extts.flags & PTP_FALLING_EDGE))
+ return -EOPNOTSUPP;
+
+ if (index >= MAX_TOD)
return -EINVAL;
- if (enable) {
- if (ref > 0xF) /* E_REF_CLK15 */
- return -EINVAL;
- if (idtcm->extts_mask & mask)
- return 0;
- err = _idtcm_set_scsr_read_trig(&idtcm->channel[todn],
- SCSR_TOD_READ_TRIG_SEL_REFCLK,
- ref);
+ if (on) {
+ /* Support triggering more than one TOD_0/1/2/3 by same pin */
+ /* Use the pin configured for the channel */
+ ref = ptp_find_pin(channel->ptp_clock, PTP_PF_EXTTS, channel->tod);
+
+ if (ref < 0) {
+ dev_err(idtcm->dev, "%s: No valid pin found for TOD%d!\n",
+ __func__, channel->tod);
+ return -EBUSY;
+ }
+
+ err = arm_tod_read_trig_sel_refclk(&idtcm->channel[index], ref);
+
if (err == 0) {
idtcm->extts_mask |= mask;
- idtcm->event_channel[todn] = channel;
- idtcm->channel[todn].refn = ref;
+ idtcm->event_channel[index] = channel;
+ idtcm->channel[index].refn = ref;
+ idtcm->extts_single_shot = is_single_shot(idtcm->extts_mask);
+
+ if (old_mask)
+ return 0;
+
+ schedule_delayed_work(&idtcm->extts_work,
+ msecs_to_jiffies(EXTTS_PERIOD_MS));
}
- } else
+ } else {
idtcm->extts_mask &= ~mask;
+ idtcm->extts_single_shot = is_single_shot(idtcm->extts_mask);
- if (old_mask == 0 && idtcm->extts_mask)
- schedule_delayed_work(&idtcm->extts_work,
- msecs_to_jiffies(EXTTS_PERIOD_MS));
+ if (idtcm->extts_mask == 0)
+ cancel_delayed_work(&idtcm->extts_work);
+ }
return err;
}
@@ -371,6 +395,31 @@ static void wait_for_chip_ready(struct idtcm *idtcm)
"Continuing while SYS APLL/DPLL is not locked");
}
+static int _idtcm_gettime_triggered(struct idtcm_channel *channel,
+ struct timespec64 *ts)
+{
+ struct idtcm *idtcm = channel->idtcm;
+ u16 tod_read_cmd = IDTCM_FW_REG(idtcm->fw_ver, V520, TOD_READ_SECONDARY_CMD);
+ u8 buf[TOD_BYTE_COUNT];
+ u8 trigger;
+ int err;
+
+ err = idtcm_read(idtcm, channel->tod_read_secondary,
+ tod_read_cmd, &trigger, sizeof(trigger));
+ if (err)
+ return err;
+
+ if (trigger & TOD_READ_TRIGGER_MASK)
+ return -EBUSY;
+
+ err = idtcm_read(idtcm, channel->tod_read_secondary,
+ TOD_READ_SECONDARY_BASE, buf, sizeof(buf));
+ if (err)
+ return err;
+
+ return char_array_to_timespec(buf, sizeof(buf), ts);
+}
+
static int _idtcm_gettime(struct idtcm_channel *channel,
struct timespec64 *ts, u8 timeout)
{
@@ -396,7 +445,7 @@ static int _idtcm_gettime(struct idtcm_channel *channel,
} while (trigger & TOD_READ_TRIGGER_MASK);
err = idtcm_read(idtcm, channel->tod_read_primary,
- TOD_READ_PRIMARY, buf, sizeof(buf));
+ TOD_READ_PRIMARY_BASE, buf, sizeof(buf));
if (err)
return err;
@@ -415,67 +464,38 @@ static int idtcm_extts_check_channel(struct idtcm *idtcm, u8 todn)
extts_channel = &idtcm->channel[todn];
ptp_channel = idtcm->event_channel[todn];
+
if (extts_channel == ptp_channel)
dco_delay = ptp_channel->dco_delay;
- err = _idtcm_gettime(extts_channel, &ts, 1);
- if (err == 0) {
- event.type = PTP_CLOCK_EXTTS;
- event.index = todn;
- event.timestamp = timespec64_to_ns(&ts) - dco_delay;
- ptp_clock_event(ptp_channel->ptp_clock, &event);
- }
- return err;
-}
+ err = _idtcm_gettime_triggered(extts_channel, &ts);
+ if (err)
+ return err;
-static u8 idtcm_enable_extts_mask(struct idtcm_channel *channel,
- u8 extts_mask, bool enable)
-{
- struct idtcm *idtcm = channel->idtcm;
- int i, err;
+ /* Triggered - save timestamp */
+ event.type = PTP_CLOCK_EXTTS;
+ event.index = todn;
+ event.timestamp = timespec64_to_ns(&ts) - dco_delay;
+ ptp_clock_event(ptp_channel->ptp_clock, &event);
- for (i = 0; i < MAX_TOD; i++) {
- u8 mask = 1 << i;
- u8 refn = idtcm->channel[i].refn;
-
- if (extts_mask & mask) {
- /* check extts before disabling it */
- if (enable == false) {
- err = idtcm_extts_check_channel(idtcm, i);
- /* trigger happened so we won't re-enable it */
- if (err == 0)
- extts_mask &= ~mask;
- }
- (void)idtcm_enable_extts(channel, i, refn, enable);
- }
- }
-
- return extts_mask;
+ return err;
}
static int _idtcm_gettime_immediate(struct idtcm_channel *channel,
struct timespec64 *ts)
{
struct idtcm *idtcm = channel->idtcm;
- u8 extts_mask = 0;
- int err;
- /* Disable extts */
- if (idtcm->extts_mask) {
- extts_mask = idtcm_enable_extts_mask(channel, idtcm->extts_mask,
- false);
- }
-
- err = _idtcm_set_scsr_read_trig(channel,
- SCSR_TOD_READ_TRIG_SEL_IMMEDIATE, 0);
- if (err == 0)
- err = _idtcm_gettime(channel, ts, 10);
+ u16 tod_read_cmd = IDTCM_FW_REG(idtcm->fw_ver, V520, TOD_READ_PRIMARY_CMD);
+ u8 val = (SCSR_TOD_READ_TRIG_SEL_IMMEDIATE << TOD_READ_TRIGGER_SHIFT);
+ int err;
- /* Re-enable extts */
- if (extts_mask)
- idtcm_enable_extts_mask(channel, extts_mask, true);
+ err = idtcm_write(idtcm, channel->tod_read_primary,
+ tod_read_cmd, &val, sizeof(val));
+ if (err)
+ return err;
- return err;
+ return _idtcm_gettime(channel, ts, 10);
}
static int _sync_pll_output(struct idtcm *idtcm,
@@ -1332,43 +1352,15 @@ static int idtcm_output_enable(struct idtcm_channel *channel,
return idtcm_write(idtcm, (u16)base, OUT_CTRL_1, &val, sizeof(val));
}
-static int idtcm_output_mask_enable(struct idtcm_channel *channel,
- bool enable)
-{
- u16 mask;
- int err;
- u8 outn;
-
- mask = channel->output_mask;
- outn = 0;
-
- while (mask) {
- if (mask & 0x1) {
- err = idtcm_output_enable(channel, enable, outn);
- if (err)
- return err;
- }
-
- mask >>= 0x1;
- outn++;
- }
-
- return 0;
-}
-
static int idtcm_perout_enable(struct idtcm_channel *channel,
struct ptp_perout_request *perout,
bool enable)
{
struct idtcm *idtcm = channel->idtcm;
- unsigned int flags = perout->flags;
struct timespec64 ts = {0, 0};
int err;
- if (flags == PEROUT_ENABLE_OUTPUT_MASK)
- err = idtcm_output_mask_enable(channel, enable);
- else
- err = idtcm_output_enable(channel, enable, perout->index);
+ err = idtcm_output_enable(channel, enable, perout->index);
if (err) {
dev_err(idtcm->dev, "Unable to set output enable");
@@ -1702,6 +1694,9 @@ static int initialize_dco_operating_mode(struct idtcm_channel *channel)
/*
* Maximum absolute value for write phase offset in picoseconds
*
+ * @channel: channel
+ * @delta_ns: delta in nanoseconds
+ *
* Destination signed register is 32-bit register in resolution of 50ps
*
* 0x7fffffff * 50 = 2147483647 * 50 = 107374182350
@@ -1869,7 +1864,7 @@ static int idtcm_adjtime(struct ptp_clock_info *ptp, s64 delta)
int err;
if (channel->phase_pull_in == true)
- return 0;
+ return -EBUSY;
mutex_lock(idtcm->lock);
@@ -1958,8 +1953,7 @@ static int idtcm_enable(struct ptp_clock_info *ptp,
err = idtcm_perout_enable(channel, &rq->perout, true);
break;
case PTP_CLK_REQ_EXTTS:
- err = idtcm_enable_extts(channel, rq->extts.index,
- rq->extts.rsv[0], on);
+ err = idtcm_extts_enable(channel, rq, on);
break;
default:
break;
@@ -1982,13 +1976,6 @@ static int idtcm_enable_tod(struct idtcm_channel *channel)
u8 cfg;
int err;
- /* STEELAI-366 - Temporary workaround for ts2phc compatibility */
- if (0) {
- err = idtcm_output_mask_enable(channel, false);
- if (err)
- return err;
- }
-
/*
* Start the TOD clock ticking.
*/
@@ -2038,17 +2025,35 @@ static void idtcm_set_version_info(struct idtcm *idtcm)
product_id, hw_rev_id, config_select);
}
+static int idtcm_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
+ enum ptp_pin_function func, unsigned int chan)
+{
+ switch (func) {
+ case PTP_PF_NONE:
+ case PTP_PF_EXTTS:
+ break;
+ case PTP_PF_PEROUT:
+ case PTP_PF_PHYSYNC:
+ return -1;
+ }
+ return 0;
+}
+
+static struct ptp_pin_desc pin_config[MAX_TOD][MAX_REF_CLK];
+
static const struct ptp_clock_info idtcm_caps = {
.owner = THIS_MODULE,
.max_adj = 244000,
.n_per_out = 12,
.n_ext_ts = MAX_TOD,
+ .n_pins = MAX_REF_CLK,
.adjphase = &idtcm_adjphase,
.adjfine = &idtcm_adjfine,
.adjtime = &idtcm_adjtime,
.gettime64 = &idtcm_gettime,
.settime64 = &idtcm_settime,
.enable = &idtcm_enable,
+ .verify = &idtcm_verify_pin,
.do_aux_work = &idtcm_work_handler,
};
@@ -2057,12 +2062,14 @@ static const struct ptp_clock_info idtcm_caps_deprecated = {
.max_adj = 244000,
.n_per_out = 12,
.n_ext_ts = MAX_TOD,
+ .n_pins = MAX_REF_CLK,
.adjphase = &idtcm_adjphase,
.adjfine = &idtcm_adjfine,
.adjtime = &idtcm_adjtime_deprecated,
.gettime64 = &idtcm_gettime,
.settime64 = &idtcm_settime_deprecated,
.enable = &idtcm_enable,
+ .verify = &idtcm_verify_pin,
.do_aux_work = &idtcm_work_handler,
};
@@ -2174,8 +2181,9 @@ static u32 idtcm_get_dco_delay(struct idtcm_channel *channel)
n = 1;
fodFreq = (u32)div_u64(m, n);
+
if (fodFreq >= 500000000)
- return 18 * (u32)div_u64(NSEC_PER_SEC, fodFreq);
+ return (u32)div_u64(18 * (u64)NSEC_PER_SEC, fodFreq);
return 0;
}
@@ -2188,24 +2196,28 @@ static int configure_channel_tod(struct idtcm_channel *channel, u32 index)
switch (index) {
case 0:
channel->tod_read_primary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_PRIMARY_0);
+ channel->tod_read_secondary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_SECONDARY_0);
channel->tod_write = IDTCM_FW_REG(fw_ver, V520, TOD_WRITE_0);
channel->tod_n = IDTCM_FW_REG(fw_ver, V520, TOD_0);
channel->sync_src = SYNC_SOURCE_DPLL0_TOD_PPS;
break;
case 1:
channel->tod_read_primary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_PRIMARY_1);
+ channel->tod_read_secondary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_SECONDARY_1);
channel->tod_write = IDTCM_FW_REG(fw_ver, V520, TOD_WRITE_1);
channel->tod_n = IDTCM_FW_REG(fw_ver, V520, TOD_1);
channel->sync_src = SYNC_SOURCE_DPLL1_TOD_PPS;
break;
case 2:
channel->tod_read_primary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_PRIMARY_2);
+ channel->tod_read_secondary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_SECONDARY_2);
channel->tod_write = IDTCM_FW_REG(fw_ver, V520, TOD_WRITE_2);
channel->tod_n = IDTCM_FW_REG(fw_ver, V520, TOD_2);
channel->sync_src = SYNC_SOURCE_DPLL2_TOD_PPS;
break;
case 3:
channel->tod_read_primary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_PRIMARY_3);
+ channel->tod_read_secondary = IDTCM_FW_REG(fw_ver, V520, TOD_READ_SECONDARY_3);
channel->tod_write = IDTCM_FW_REG(fw_ver, V520, TOD_WRITE_3);
channel->tod_n = IDTCM_FW_REG(fw_ver, V520, TOD_3);
channel->sync_src = SYNC_SOURCE_DPLL3_TOD_PPS;
@@ -2221,6 +2233,7 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
{
struct idtcm_channel *channel;
int err;
+ int i;
if (!(index < MAX_TOD))
return -EINVAL;
@@ -2248,6 +2261,17 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
snprintf(channel->caps.name, sizeof(channel->caps.name),
"IDT CM TOD%u", index);
+ channel->caps.pin_config = pin_config[index];
+
+ for (i = 0; i < channel->caps.n_pins; ++i) {
+ struct ptp_pin_desc *ppd = &channel->caps.pin_config[i];
+
+ snprintf(ppd->name, sizeof(ppd->name), "input_ref%d", i);
+ ppd->index = i;
+ ppd->func = PTP_PF_NONE;
+ ppd->chan = index;
+ }
+
err = initialize_dco_operating_mode(channel);
if (err)
return err;
@@ -2302,26 +2326,40 @@ static int idtcm_enable_extts_channel(struct idtcm *idtcm, u32 index)
static void idtcm_extts_check(struct work_struct *work)
{
struct idtcm *idtcm = container_of(work, struct idtcm, extts_work.work);
- int err, i;
+ struct idtcm_channel *channel;
+ u8 mask;
+ int err;
+ int i;
if (idtcm->extts_mask == 0)
return;
mutex_lock(idtcm->lock);
+
for (i = 0; i < MAX_TOD; i++) {
- u8 mask = 1 << i;
+ mask = 1 << i;
+
+ if ((idtcm->extts_mask & mask) == 0)
+ continue;
- if (idtcm->extts_mask & mask) {
- err = idtcm_extts_check_channel(idtcm, i);
+ err = idtcm_extts_check_channel(idtcm, i);
+
+ if (err == 0) {
/* trigger clears itself, so clear the mask */
- if (err == 0)
+ if (idtcm->extts_single_shot) {
idtcm->extts_mask &= ~mask;
+ } else {
+ /* Re-arm */
+ channel = &idtcm->channel[i];
+ arm_tod_read_trig_sel_refclk(channel, channel->refn);
+ }
}
}
if (idtcm->extts_mask)
schedule_delayed_work(&idtcm->extts_work,
msecs_to_jiffies(EXTTS_PERIOD_MS));
+
mutex_unlock(idtcm->lock);
}
@@ -2342,6 +2380,11 @@ static void set_default_masks(struct idtcm *idtcm)
idtcm->tod_mask = DEFAULT_TOD_MASK;
idtcm->extts_mask = 0;
+ idtcm->channel[0].tod = 0;
+ idtcm->channel[1].tod = 1;
+ idtcm->channel[2].tod = 2;
+ idtcm->channel[3].tod = 3;
+
idtcm->channel[0].pll = DEFAULT_TOD0_PTP_PLL;
idtcm->channel[1].pll = DEFAULT_TOD1_PTP_PLL;
idtcm->channel[2].pll = DEFAULT_TOD2_PTP_PLL;
@@ -2420,8 +2463,8 @@ static int idtcm_remove(struct platform_device *pdev)
{
struct idtcm *idtcm = platform_get_drvdata(pdev);
+ idtcm->extts_mask = 0;
ptp_clock_unregister_all(idtcm);
-
cancel_delayed_work_sync(&idtcm->extts_work);
return 0;
diff --git a/drivers/ptp/ptp_clockmatrix.h b/drivers/ptp/ptp_clockmatrix.h
index 0f3059ae1fff..bf1e49409844 100644
--- a/drivers/ptp/ptp_clockmatrix.h
+++ b/drivers/ptp/ptp_clockmatrix.h
@@ -10,11 +10,13 @@
#include <linux/ktime.h>
#include <linux/mfd/idt8a340_reg.h>
+#include <linux/ptp_clock.h>
#include <linux/regmap.h>
#define FW_FILENAME "idtcm.bin"
#define MAX_TOD (4)
#define MAX_PLL (8)
+#define MAX_REF_CLK (16)
#define MAX_ABS_WRITE_PHASE_PICOSECONDS (107374182350LL)
@@ -52,8 +54,6 @@
#define LOCK_TIMEOUT_MS (2000)
#define LOCK_POLL_INTERVAL_MS (10)
-#define PEROUT_ENABLE_OUTPUT_MASK (0xdeadbeef)
-
#define IDTCM_MAX_WRITE_COUNT (512)
#define PHASE_PULL_IN_MAX_PPB (144000)
@@ -90,6 +90,7 @@ struct idtcm_channel {
u16 dpll_ctrl_n;
u16 dpll_phase_pull_in;
u16 tod_read_primary;
+ u16 tod_read_secondary;
u16 tod_write;
u16 tod_n;
u16 hw_dpll_n;
@@ -105,6 +106,7 @@ struct idtcm_channel {
/* last input trigger for extts */
u8 refn;
u8 pll;
+ u8 tod;
u16 output_mask;
};
@@ -116,6 +118,7 @@ struct idtcm {
enum fw_version fw_ver;
/* Polls for external time stamps */
u8 extts_mask;
+ bool extts_single_shot;
struct delayed_work extts_work;
/* Remember the ptp channel to report extts */
struct idtcm_channel *event_channel[MAX_TOD];
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index dd45471f6780..860672d6a03c 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -300,7 +300,7 @@ struct ptp_ocp {
struct platform_device *spi_flash;
struct clk_hw *i2c_clk;
struct timer_list watchdog;
- const struct ocp_attr_group *attr_tbl;
+ const struct attribute_group **attr_group;
const struct ptp_ocp_eeprom_map *eeprom_map;
struct dentry *debug_root;
time64_t gnss_lost;
@@ -841,7 +841,7 @@ __ptp_ocp_adjtime_locked(struct ptp_ocp *bp, u32 adj_val)
}
static void
-ptp_ocp_adjtime_coarse(struct ptp_ocp *bp, u64 delta_ns)
+ptp_ocp_adjtime_coarse(struct ptp_ocp *bp, s64 delta_ns)
{
struct timespec64 ts;
unsigned long flags;
@@ -850,7 +850,8 @@ ptp_ocp_adjtime_coarse(struct ptp_ocp *bp, u64 delta_ns)
spin_lock_irqsave(&bp->lock, flags);
err = __ptp_ocp_gettime_locked(bp, &ts, NULL);
if (likely(!err)) {
- timespec64_add_ns(&ts, delta_ns);
+ set_normalized_timespec64(&ts, ts.tv_sec,
+ ts.tv_nsec + delta_ns);
__ptp_ocp_settime_locked(bp, &ts);
}
spin_unlock_irqrestore(&bp->lock, flags);
@@ -1836,6 +1837,42 @@ ptp_ocp_signal_init(struct ptp_ocp *bp)
}
static void
+ptp_ocp_attr_group_del(struct ptp_ocp *bp)
+{
+ sysfs_remove_groups(&bp->dev.kobj, bp->attr_group);
+ kfree(bp->attr_group);
+}
+
+static int
+ptp_ocp_attr_group_add(struct ptp_ocp *bp,
+ const struct ocp_attr_group *attr_tbl)
+{
+ int count, i;
+ int err;
+
+ count = 0;
+ for (i = 0; attr_tbl[i].cap; i++)
+ if (attr_tbl[i].cap & bp->fw_cap)
+ count++;
+
+ bp->attr_group = kcalloc(count + 1, sizeof(struct attribute_group *),
+ GFP_KERNEL);
+ if (!bp->attr_group)
+ return -ENOMEM;
+
+ count = 0;
+ for (i = 0; attr_tbl[i].cap; i++)
+ if (attr_tbl[i].cap & bp->fw_cap)
+ bp->attr_group[count++] = attr_tbl[i].group;
+
+ err = sysfs_create_groups(&bp->dev.kobj, bp->attr_group);
+ if (err)
+ bp->attr_group[0] = NULL;
+
+ return err;
+}
+
+static void
ptp_ocp_sma_init(struct ptp_ocp *bp)
{
u32 reg;
@@ -1904,7 +1941,6 @@ ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
bp->flash_start = 1024 * 4096;
bp->eeprom_map = fb_eeprom_map;
bp->fw_version = ioread32(&bp->image->version);
- bp->attr_tbl = fb_timecard_groups;
bp->fw_cap = OCP_CAP_BASIC;
ver = bp->fw_version & 0xffff;
@@ -1918,6 +1954,10 @@ ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
ptp_ocp_sma_init(bp);
ptp_ocp_signal_init(bp);
+ err = ptp_ocp_attr_group_add(bp, fb_timecard_groups);
+ if (err)
+ return err;
+
err = ptp_ocp_fb_set_pins(bp);
if (err)
return err;
@@ -3388,7 +3428,6 @@ ptp_ocp_complete(struct ptp_ocp *bp)
{
struct pps_device *pps;
char buf[32];
- int i, err;
if (bp->gnss_port != -1) {
sprintf(buf, "ttyS%d", bp->gnss_port);
@@ -3413,14 +3452,6 @@ ptp_ocp_complete(struct ptp_ocp *bp)
if (pps)
ptp_ocp_symlink(bp, pps->dev, "pps");
- for (i = 0; bp->attr_tbl[i].cap; i++) {
- if (!(bp->attr_tbl[i].cap & bp->fw_cap))
- continue;
- err = sysfs_create_group(&bp->dev.kobj, bp->attr_tbl[i].group);
- if (err)
- return err;
- }
-
ptp_ocp_debugfs_add_device(bp);
return 0;
@@ -3492,15 +3523,11 @@ static void
ptp_ocp_detach_sysfs(struct ptp_ocp *bp)
{
struct device *dev = &bp->dev;
- int i;
sysfs_remove_link(&dev->kobj, "ttyGNSS");
sysfs_remove_link(&dev->kobj, "ttyMAC");
sysfs_remove_link(&dev->kobj, "ptp");
sysfs_remove_link(&dev->kobj, "pps");
- if (bp->attr_tbl)
- for (i = 0; bp->attr_tbl[i].cap; i++)
- sysfs_remove_group(&dev->kobj, bp->attr_tbl[i].group);
}
static void
@@ -3510,6 +3537,7 @@ ptp_ocp_detach(struct ptp_ocp *bp)
ptp_ocp_debugfs_remove_device(bp);
ptp_ocp_detach_sysfs(bp);
+ ptp_ocp_attr_group_del(bp);
if (timer_pending(&bp->watchdog))
del_timer_sync(&bp->watchdog);
if (bp->ts0)
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 37d06f993b76..1d9be771f3ee 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -1172,9 +1172,8 @@ static blk_status_t alua_prep_fn(struct scsi_device *sdev, struct request *req)
case SCSI_ACCESS_STATE_OPTIMAL:
case SCSI_ACCESS_STATE_ACTIVE:
case SCSI_ACCESS_STATE_LBA:
- return BLK_STS_OK;
case SCSI_ACCESS_STATE_TRANSITIONING:
- return BLK_STS_AGAIN;
+ return BLK_STS_OK;
default:
req->rq_flags |= RQF_QUIET;
return BLK_STS_IOERR;
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 44ca6110213c..79b2827e4081 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -667,7 +667,7 @@ static void fcoe_netdev_features_change(struct fc_lport *lport,
if (netdev->features & NETIF_F_FSO) {
lport->seq_offload = 1;
- lport->lso_max = netdev->gso_max_size;
+ lport->lso_max = min(netdev->gso_max_size, GSO_LEGACY_MAX_SIZE);
FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
lport->lso_max);
} else {
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index ef6e8cd8c26a..872a26376ccb 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1330,7 +1330,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
LPFC_SLI_INTF_IF_TYPE_0) {
/* FLOGI needs to be 3 for WQE FCFI */
- ct = ((SLI4_CT_FCFI >> 1) & 1) | (SLI4_CT_FCFI & 1);
+ ct = SLI4_CT_FCFI;
bf_set(wqe_ct, &wqe->els_req.wqe_com, ct);
/* Set the fcfi to the fcfi we registered with */
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index bda2a7ba4e77..6adaf79e67cc 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -10720,10 +10720,10 @@ __lpfc_sli_prep_gen_req_s4(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp,
/* Words 0 - 2 */
bde = (struct ulp_bde64_le *)&cmdwqe->generic.bde;
- bde->addr_low = cpu_to_le32(putPaddrLow(bmp->phys));
- bde->addr_high = cpu_to_le32(putPaddrHigh(bmp->phys));
+ bde->addr_low = bpl->addr_low;
+ bde->addr_high = bpl->addr_high;
bde->type_size = cpu_to_le32(xmit_len);
- bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BLP_64);
+ bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64);
/* Word 3 */
cmdwqe->gen_req.request_payload_len = xmit_len;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 85dbf81f3204..6dfcfd8e7337 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -3826,6 +3826,9 @@ int qlt_abort_cmd(struct qla_tgt_cmd *cmd)
spin_lock_irqsave(&cmd->cmd_lock, flags);
if (cmd->aborted) {
+ if (cmd->sg_mapped)
+ qlt_unmap_sg(vha, cmd);
+
spin_unlock_irqrestore(&cmd->cmd_lock, flags);
/*
* It's normal to see 2 calls in this path:
diff --git a/drivers/slimbus/qcom-ctrl.c b/drivers/slimbus/qcom-ctrl.c
index f04b961b96cd..ec58091fc948 100644
--- a/drivers/slimbus/qcom-ctrl.c
+++ b/drivers/slimbus/qcom-ctrl.c
@@ -510,9 +510,9 @@ static int qcom_slim_probe(struct platform_device *pdev)
}
ctrl->irq = platform_get_irq(pdev, 0);
- if (!ctrl->irq) {
+ if (ctrl->irq < 0) {
dev_err(&pdev->dev, "no slimbus IRQ\n");
- return -ENODEV;
+ return ctrl->irq;
}
sctrl = &ctrl->ctrl;
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 148bcb99c212..493bebbba521 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -914,7 +914,6 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
err = 0;
goto out_free;
}
- pr_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
}
}
err = sprom_extract(bus, sprom, buf, bus->sprom_size);
diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
index d97f496bab9b..79931ddc582a 100644
--- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
@@ -194,12 +194,31 @@ static int int3400_thermal_run_osc(acpi_handle handle, char *uuid_str, int *enab
return result;
}
+static int set_os_uuid_mask(struct int3400_thermal_priv *priv, u32 mask)
+{
+ int cap = 0;
+
+ /*
+ * Capability bits:
+ * Bit 0: set to 1 to indicate DPTF is active
+ * Bi1 1: set to 1 to active cooling is supported by user space daemon
+ * Bit 2: set to 1 to passive cooling is supported by user space daemon
+ * Bit 3: set to 1 to critical trip is handled by user space daemon
+ */
+ if (mask)
+ cap = (priv->os_uuid_mask << 1) | 0x01;
+
+ return int3400_thermal_run_osc(priv->adev->handle,
+ "b23ba85d-c8b7-3542-88de-8de2ffcfd698",
+ &cap);
+}
+
static ssize_t current_uuid_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
- int i;
+ int ret, i;
for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; ++i) {
if (!strncmp(buf, int3400_thermal_uuids[i],
@@ -231,19 +250,7 @@ static ssize_t current_uuid_store(struct device *dev,
}
if (priv->os_uuid_mask) {
- int cap, ret;
-
- /*
- * Capability bits:
- * Bit 0: set to 1 to indicate DPTF is active
- * Bi1 1: set to 1 to active cooling is supported by user space daemon
- * Bit 2: set to 1 to passive cooling is supported by user space daemon
- * Bit 3: set to 1 to critical trip is handled by user space daemon
- */
- cap = ((priv->os_uuid_mask << 1) | 0x01);
- ret = int3400_thermal_run_osc(priv->adev->handle,
- "b23ba85d-c8b7-3542-88de-8de2ffcfd698",
- &cap);
+ ret = set_os_uuid_mask(priv, priv->os_uuid_mask);
if (ret)
return ret;
}
@@ -469,17 +476,26 @@ static int int3400_thermal_change_mode(struct thermal_zone_device *thermal,
if (mode != thermal->mode) {
int enabled;
+ enabled = mode == THERMAL_DEVICE_ENABLED;
+
+ if (priv->os_uuid_mask) {
+ if (!enabled) {
+ priv->os_uuid_mask = 0;
+ result = set_os_uuid_mask(priv, priv->os_uuid_mask);
+ }
+ goto eval_odvp;
+ }
+
if (priv->current_uuid_index < 0 ||
priv->current_uuid_index >= INT3400_THERMAL_MAXIMUM_UUID)
return -EINVAL;
- enabled = (mode == THERMAL_DEVICE_ENABLED);
result = int3400_thermal_run_osc(priv->adev->handle,
int3400_thermal_uuids[priv->current_uuid_index],
&enabled);
}
-
+eval_odvp:
evaluate_odvp(priv);
return result;
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index a38b922bcbc1..fd8b86dde525 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -137,6 +137,7 @@ struct gsm_dlci {
int retries;
/* Uplink tty if active */
struct tty_port port; /* The tty bound to this DLCI if there is one */
+#define TX_SIZE 4096 /* Must be power of 2. */
struct kfifo fifo; /* Queue fifo for the DLCI */
int adaption; /* Adaption layer in use */
int prev_adaption;
@@ -1658,6 +1659,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
if (len == 0)
return;
}
+ len--;
slen++;
tty = tty_port_tty_get(port);
if (tty) {
@@ -1730,7 +1732,7 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
return NULL;
spin_lock_init(&dlci->lock);
mutex_init(&dlci->mutex);
- if (kfifo_alloc(&dlci->fifo, 4096, GFP_KERNEL) < 0) {
+ if (kfifo_alloc(&dlci->fifo, TX_SIZE, GFP_KERNEL) < 0) {
kfree(dlci);
return NULL;
}
@@ -2351,6 +2353,7 @@ static void gsm_copy_config_values(struct gsm_mux *gsm,
static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
{
+ int ret = 0;
int need_close = 0;
int need_restart = 0;
@@ -2418,10 +2421,13 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
* FIXME: We need to separate activation/deactivation from adding
* and removing from the mux array
*/
- if (need_restart)
- gsm_activate_mux(gsm);
- if (gsm->initiator && need_close)
- gsm_dlci_begin_open(gsm->dlci[0]);
+ if (gsm->dead) {
+ ret = gsm_activate_mux(gsm);
+ if (ret)
+ return ret;
+ if (gsm->initiator)
+ gsm_dlci_begin_open(gsm->dlci[0]);
+ }
return 0;
}
@@ -2971,8 +2977,6 @@ static struct tty_ldisc_ops tty_ldisc_packet = {
* Virtual tty side
*/
-#define TX_SIZE 512
-
/**
* gsm_modem_upd_via_data - send modem bits via convergence layer
* @dlci: channel
@@ -3212,7 +3216,7 @@ static unsigned int gsmtty_write_room(struct tty_struct *tty)
struct gsm_dlci *dlci = tty->driver_data;
if (dlci->state == DLCI_CLOSED)
return 0;
- return TX_SIZE - kfifo_len(&dlci->fifo);
+ return kfifo_avail(&dlci->fifo);
}
static unsigned int gsmtty_chars_in_buffer(struct tty_struct *tty)
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index f4a0caa56f84..21053db93ff1 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -37,6 +37,7 @@
#define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */
#define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */
+#define MTK_UART_EFR 38 /* I/O: Extended Features Register */
#define MTK_UART_EFR_EN 0x10 /* Enable enhancement feature */
#define MTK_UART_EFR_RTS 0x40 /* Enable hardware rx flow control */
#define MTK_UART_EFR_CTS 0x80 /* Enable hardware tx flow control */
@@ -53,6 +54,12 @@
#define MTK_UART_TX_TRIGGER 1
#define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE
+#define MTK_UART_FEATURE_SEL 39 /* Feature Selection register */
+#define MTK_UART_FEAT_NEWRMAP BIT(0) /* Use new register map */
+
+#define MTK_UART_XON1 40 /* I/O: Xon character 1 */
+#define MTK_UART_XOFF1 42 /* I/O: Xoff character 1 */
+
#ifdef CONFIG_SERIAL_8250_DMA
enum dma_rx_status {
DMA_RX_START = 0,
@@ -169,7 +176,7 @@ static void mtk8250_dma_enable(struct uart_8250_port *up)
MTK_UART_DMA_EN_RX | MTK_UART_DMA_EN_TX);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, UART_EFR_ECB);
+ serial_out(up, MTK_UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, lcr);
if (dmaengine_slave_config(dma->rxchan, &dma->rxconf) != 0)
@@ -232,7 +239,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
int lcr = serial_in(up, UART_LCR);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, UART_EFR_ECB);
+ serial_out(up, MTK_UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, lcr);
lcr = serial_in(up, UART_LCR);
@@ -241,7 +248,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR);
serial_out(up, MTK_UART_ESCAPE_EN, 0x00);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, serial_in(up, UART_EFR) &
+ serial_out(up, MTK_UART_EFR, serial_in(up, MTK_UART_EFR) &
(~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)));
serial_out(up, UART_LCR, lcr);
mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI |
@@ -255,8 +262,8 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
/*enable hw flow control*/
- serial_out(up, UART_EFR, MTK_UART_EFR_HW_FC |
- (serial_in(up, UART_EFR) &
+ serial_out(up, MTK_UART_EFR, MTK_UART_EFR_HW_FC |
+ (serial_in(up, MTK_UART_EFR) &
(~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))));
serial_out(up, UART_LCR, lcr);
@@ -270,12 +277,12 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
/*enable sw flow control */
- serial_out(up, UART_EFR, MTK_UART_EFR_XON1_XOFF1 |
- (serial_in(up, UART_EFR) &
+ serial_out(up, MTK_UART_EFR, MTK_UART_EFR_XON1_XOFF1 |
+ (serial_in(up, MTK_UART_EFR) &
(~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))));
- serial_out(up, UART_XON1, START_CHAR(port->state->port.tty));
- serial_out(up, UART_XOFF1, STOP_CHAR(port->state->port.tty));
+ serial_out(up, MTK_UART_XON1, START_CHAR(port->state->port.tty));
+ serial_out(up, MTK_UART_XOFF1, STOP_CHAR(port->state->port.tty));
serial_out(up, UART_LCR, lcr);
mtk8250_disable_intrs(up, MTK_UART_IER_CTSI|MTK_UART_IER_RTSI);
mtk8250_enable_intrs(up, MTK_UART_IER_XOFFI);
@@ -568,6 +575,10 @@ static int mtk8250_probe(struct platform_device *pdev)
uart.dma = data->dma;
#endif
+ /* Set AP UART new register map */
+ writel(MTK_UART_FEAT_NEWRMAP, uart.port.membase +
+ (MTK_UART_FEATURE_SEL << uart.port.regshift));
+
/* Disable Rate Fix function */
writel(0x0, uart.port.membase +
(MTK_UART_RATE_FIX << uart.port.regshift));
diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c
index 6d70fea76bb3..e37a917b9dbb 100644
--- a/drivers/tty/serial/digicolor-usart.c
+++ b/drivers/tty/serial/digicolor-usart.c
@@ -471,11 +471,10 @@ static int digicolor_uart_probe(struct platform_device *pdev)
if (IS_ERR(uart_clk))
return PTR_ERR(uart_clk);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dp->port.mapbase = res->start;
- dp->port.membase = devm_ioremap_resource(&pdev->dev, res);
+ dp->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(dp->port.membase))
return PTR_ERR(dp->port.membase);
+ dp->port.mapbase = res->start;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 87789872f400..be12fee94db5 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -2664,6 +2664,7 @@ static int lpuart_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct lpuart_port *sport;
struct resource *res;
+ irq_handler_t handler;
int ret;
sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
@@ -2741,17 +2742,11 @@ static int lpuart_probe(struct platform_device *pdev)
if (lpuart_is_32(sport)) {
lpuart_reg.cons = LPUART32_CONSOLE;
- ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart32_int, 0,
- DRIVER_NAME, sport);
+ handler = lpuart32_int;
} else {
lpuart_reg.cons = LPUART_CONSOLE;
- ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart_int, 0,
- DRIVER_NAME, sport);
+ handler = lpuart_int;
}
-
- if (ret)
- goto failed_irq_request;
-
ret = uart_add_one_port(&lpuart_reg, &sport->port);
if (ret)
goto failed_attach_port;
@@ -2773,13 +2768,18 @@ static int lpuart_probe(struct platform_device *pdev)
sport->port.rs485_config(&sport->port, &sport->port.rs485);
+ ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0,
+ DRIVER_NAME, sport);
+ if (ret)
+ goto failed_irq_request;
+
return 0;
+failed_irq_request:
failed_get_rs485:
failed_reset:
uart_remove_one_port(&lpuart_reg, &sport->port);
failed_attach_port:
-failed_irq_request:
lpuart_disable_clks(sport);
failed_clock_enable:
failed_out_of_range:
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 7f2c83f299d3..eebe782380fb 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -774,6 +774,7 @@ static int wdm_release(struct inode *inode, struct file *file)
poison_urbs(desc);
spin_lock_irq(&desc->iuspin);
desc->resp_count = 0;
+ clear_bit(WDM_RESPONDING, &desc->flags);
spin_unlock_irq(&desc->iuspin);
desc->manage_power(desc->intf, 0);
unpoison_urbs(desc);
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index 71bb5e477dba..d37965867b23 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -890,13 +890,37 @@ static void uvc_function_unbind(struct usb_configuration *c,
{
struct usb_composite_dev *cdev = c->cdev;
struct uvc_device *uvc = to_uvc(f);
+ long wait_ret = 1;
uvcg_info(f, "%s()\n", __func__);
+ /* If we know we're connected via v4l2, then there should be a cleanup
+ * of the device from userspace either via UVC_EVENT_DISCONNECT or
+ * though the video device removal uevent. Allow some time for the
+ * application to close out before things get deleted.
+ */
+ if (uvc->func_connected) {
+ uvcg_dbg(f, "waiting for clean disconnect\n");
+ wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue,
+ uvc->func_connected == false, msecs_to_jiffies(500));
+ uvcg_dbg(f, "done waiting with ret: %ld\n", wait_ret);
+ }
+
device_remove_file(&uvc->vdev.dev, &dev_attr_function_name);
video_unregister_device(&uvc->vdev);
v4l2_device_unregister(&uvc->v4l2_dev);
+ if (uvc->func_connected) {
+ /* Wait for the release to occur to ensure there are no longer any
+ * pending operations that may cause panics when resources are cleaned
+ * up.
+ */
+ uvcg_warn(f, "%s no clean disconnect, wait for release\n", __func__);
+ wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue,
+ uvc->func_connected == false, msecs_to_jiffies(1000));
+ uvcg_dbg(f, "done waiting for release with ret: %ld\n", wait_ret);
+ }
+
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
@@ -915,6 +939,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
mutex_init(&uvc->video.mutex);
uvc->state = UVC_STATE_DISCONNECTED;
+ init_waitqueue_head(&uvc->func_connected_queue);
opts = fi_to_f_uvc_opts(fi);
mutex_lock(&opts->lock);
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
index c3607a32b986..886103a1fe9b 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -14,6 +14,7 @@
#include <linux/spinlock.h>
#include <linux/usb/composite.h>
#include <linux/videodev2.h>
+#include <linux/wait.h>
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
@@ -129,6 +130,7 @@ struct uvc_device {
struct usb_function func;
struct uvc_video video;
bool func_connected;
+ wait_queue_head_t func_connected_queue;
/* Descriptors */
struct {
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
index a2c78690c5c2..fd8f73bb726d 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
@@ -253,10 +253,11 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh,
static void uvc_v4l2_disable(struct uvc_device *uvc)
{
- uvc->func_connected = false;
uvc_function_disconnect(uvc);
uvcg_video_enable(&uvc->video, 0);
uvcg_free_buffers(&uvc->video.queue);
+ uvc->func_connected = false;
+ wake_up_interruptible(&uvc->func_connected_queue);
}
static int
diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
index 8d40a1f2ec57..e9440f7bf019 100644
--- a/drivers/usb/gadget/legacy/raw_gadget.c
+++ b/drivers/usb/gadget/legacy/raw_gadget.c
@@ -145,6 +145,7 @@ enum dev_state {
STATE_DEV_INVALID = 0,
STATE_DEV_OPENED,
STATE_DEV_INITIALIZED,
+ STATE_DEV_REGISTERING,
STATE_DEV_RUNNING,
STATE_DEV_CLOSED,
STATE_DEV_FAILED
@@ -508,6 +509,7 @@ static int raw_ioctl_run(struct raw_dev *dev, unsigned long value)
ret = -EINVAL;
goto out_unlock;
}
+ dev->state = STATE_DEV_REGISTERING;
spin_unlock_irqrestore(&dev->lock, flags);
ret = usb_gadget_probe_driver(&dev->driver);
diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index f3139ce7b0a9..06a6b19acaae 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -19,11 +19,6 @@
#define HS_BW_BOUNDARY 6144
/* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
#define FS_PAYLOAD_MAX 188
-/*
- * max number of microframes for split transfer,
- * for fs isoc in : 1 ss + 1 idle + 7 cs
- */
-#define TT_MICROFRAMES_MAX 9
#define DBG_BUF_EN 64
@@ -242,28 +237,17 @@ static void drop_tt(struct usb_device *udev)
static struct mu3h_sch_ep_info *
create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
- struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
+ struct usb_host_endpoint *ep)
{
struct mu3h_sch_ep_info *sch_ep;
struct mu3h_sch_bw_info *bw_info;
struct mu3h_sch_tt *tt = NULL;
- u32 len_bw_budget_table;
bw_info = get_bw_info(mtk, udev, ep);
if (!bw_info)
return ERR_PTR(-ENODEV);
- if (is_fs_or_ls(udev->speed))
- len_bw_budget_table = TT_MICROFRAMES_MAX;
- else if ((udev->speed >= USB_SPEED_SUPER)
- && usb_endpoint_xfer_isoc(&ep->desc))
- len_bw_budget_table = get_esit(ep_ctx);
- else
- len_bw_budget_table = 1;
-
- sch_ep = kzalloc(struct_size(sch_ep, bw_budget_table,
- len_bw_budget_table),
- GFP_KERNEL);
+ sch_ep = kzalloc(sizeof(*sch_ep), GFP_KERNEL);
if (!sch_ep)
return ERR_PTR(-ENOMEM);
@@ -295,8 +279,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
u32 mult;
u32 esit_pkts;
u32 max_esit_payload;
- u32 *bwb_table = sch_ep->bw_budget_table;
- int i;
ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
@@ -332,7 +314,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
*/
sch_ep->pkts = max_burst + 1;
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
- bwb_table[0] = sch_ep->bw_cost_per_microframe;
} else if (sch_ep->speed >= USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0;
@@ -349,7 +330,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
sch_ep->pkts = esit_pkts;
sch_ep->num_budget_microframes = 1;
- bwb_table[0] = maxpkt * sch_ep->pkts;
}
if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
@@ -366,15 +346,8 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
DIV_ROUND_UP(esit_pkts, sch_ep->pkts);
sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1);
- sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
-
- for (i = 0; i < sch_ep->num_budget_microframes - 1; i++)
- bwb_table[i] = sch_ep->bw_cost_per_microframe;
-
- /* last one <= bw_cost_per_microframe */
- bwb_table[i] = maxpkt * esit_pkts
- - i * sch_ep->bw_cost_per_microframe;
}
+ sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
} else if (is_fs_or_ls(sch_ep->speed)) {
sch_ep->pkts = 1; /* at most one packet for each microframe */
@@ -384,28 +357,7 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
*/
sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX);
sch_ep->num_budget_microframes = sch_ep->cs_count;
- sch_ep->bw_cost_per_microframe =
- (maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX;
-
- /* init budget table */
- if (ep_type == ISOC_OUT_EP) {
- for (i = 0; i < sch_ep->num_budget_microframes; i++)
- bwb_table[i] = sch_ep->bw_cost_per_microframe;
- } else if (ep_type == INT_OUT_EP) {
- /* only first one consumes bandwidth, others as zero */
- bwb_table[0] = sch_ep->bw_cost_per_microframe;
- } else { /* INT_IN_EP or ISOC_IN_EP */
- bwb_table[0] = 0; /* start split */
- bwb_table[1] = 0; /* idle */
- /*
- * due to cs_count will be updated according to cs
- * position, assign all remainder budget array
- * elements as @bw_cost_per_microframe, but only first
- * @num_budget_microframes elements will be used later
- */
- for (i = 2; i < TT_MICROFRAMES_MAX; i++)
- bwb_table[i] = sch_ep->bw_cost_per_microframe;
- }
+ sch_ep->bw_cost_per_microframe = min_t(u32, maxpkt, FS_PAYLOAD_MAX);
}
}
@@ -422,7 +374,7 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
k = XHCI_MTK_BW_INDEX(base + j);
- bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j];
+ bw = sch_bw->bus_bw[k] + sch_ep->bw_cost_per_microframe;
if (bw > max_bw)
max_bw = bw;
}
@@ -433,18 +385,16 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
struct mu3h_sch_ep_info *sch_ep, bool used)
{
+ int bw_updated;
u32 base;
- int i, j, k;
+ int i, j;
+
+ bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1);
for (i = 0; i < sch_ep->num_esit; i++) {
base = sch_ep->offset + i * sch_ep->esit;
- for (j = 0; j < sch_ep->num_budget_microframes; j++) {
- k = XHCI_MTK_BW_INDEX(base + j);
- if (used)
- sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j];
- else
- sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j];
- }
+ for (j = 0; j < sch_ep->num_budget_microframes; j++)
+ sch_bw->bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated;
}
}
@@ -464,7 +414,7 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
*/
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
k = XHCI_MTK_BW_INDEX(base + j);
- tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j];
+ tmp = tt->fs_bus_bw[k] + sch_ep->bw_cost_per_microframe;
if (tmp > FS_PAYLOAD_MAX)
return -ESCH_BW_OVERFLOW;
}
@@ -538,19 +488,17 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
{
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
+ int bw_updated;
u32 base;
- int i, j, k;
+ int i, j;
+
+ bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1);
for (i = 0; i < sch_ep->num_esit; i++) {
base = sch_ep->offset + i * sch_ep->esit;
- for (j = 0; j < sch_ep->num_budget_microframes; j++) {
- k = XHCI_MTK_BW_INDEX(base + j);
- if (used)
- tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j];
- else
- tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j];
- }
+ for (j = 0; j < sch_ep->num_budget_microframes; j++)
+ tt->fs_bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated;
}
if (used)
@@ -710,7 +658,7 @@ static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
- sch_ep = create_sch_ep(mtk, udev, ep, ep_ctx);
+ sch_ep = create_sch_ep(mtk, udev, ep);
if (IS_ERR_OR_NULL(sch_ep))
return -ENOMEM;
diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
index ffd4b493b4ba..1174a510dd38 100644
--- a/drivers/usb/host/xhci-mtk.h
+++ b/drivers/usb/host/xhci-mtk.h
@@ -83,7 +83,6 @@ struct mu3h_sch_bw_info {
* times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets
* according to @pkts and @repeat. normal mode is used by
* default
- * @bw_budget_table: table to record bandwidth budget per microframe
*/
struct mu3h_sch_ep_info {
u32 esit;
@@ -109,7 +108,6 @@ struct mu3h_sch_ep_info {
u32 pkts;
u32 cs_count;
u32 burst_mode;
- u32 bw_budget_table[];
};
#define MU3C_U3_PORT_MAX 4
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 1364ce7f0abf..152ad882657d 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -2123,10 +2123,14 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(3) },
{ USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */
.driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
+ { USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
+ { USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */
{ USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */
.driver_info = RSVD(4) | RSVD(5) },
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */
.driver_info = RSVD(6) },
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0106, 0xff) }, /* Fibocom MA510 (ECM mode w/ diag intf.) */
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x010a, 0xff) }, /* Fibocom MA510 (ECM mode) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 88b284d61681..1d878d05a658 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -106,6 +106,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_LM920_PRODUCT_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_LM930_PRODUCT_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_LM940_PRODUCT_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_TD620_PRODUCT_ID) },
{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index c5406452b774..732f9b13ad5d 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -135,6 +135,7 @@
#define HP_TD620_PRODUCT_ID 0x0956
#define HP_LD960_PRODUCT_ID 0x0b39
#define HP_LD381_PRODUCT_ID 0x0f7f
+#define HP_LM930_PRODUCT_ID 0x0f9b
#define HP_LCM220_PRODUCT_ID 0x3139
#define HP_LCM960_PRODUCT_ID 0x3239
#define HP_LD220_PRODUCT_ID 0x3524
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index c18bf8164bc2..586ef5551e76 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -166,6 +166,8 @@ static const struct usb_device_id id_table[] = {
{DEVICE_SWI(0x1199, 0x9090)}, /* Sierra Wireless EM7565 QDL */
{DEVICE_SWI(0x1199, 0x9091)}, /* Sierra Wireless EM7565 */
{DEVICE_SWI(0x1199, 0x90d2)}, /* Sierra Wireless EM9191 QDL */
+ {DEVICE_SWI(0x1199, 0xc080)}, /* Sierra Wireless EM7590 QDL */
+ {DEVICE_SWI(0x1199, 0xc081)}, /* Sierra Wireless EM7590 */
{DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
{DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
{DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index e07d26a3cd8e..f33e08eb7670 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -877,7 +877,7 @@ static int tcpci_remove(struct i2c_client *client)
/* Disable chip interrupts before unregistering port */
err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, 0);
if (err < 0)
- return err;
+ dev_warn(&client->dev, "Failed to disable irqs (%pe)\n", ERR_PTR(err));
tcpci_unregister_port(chip->tcpci);
diff --git a/drivers/usb/typec/tcpm/tcpci_mt6360.c b/drivers/usb/typec/tcpm/tcpci_mt6360.c
index f1bd9e09bc87..8a952eaf9016 100644
--- a/drivers/usb/typec/tcpm/tcpci_mt6360.c
+++ b/drivers/usb/typec/tcpm/tcpci_mt6360.c
@@ -15,6 +15,9 @@
#include "tcpci.h"
+#define MT6360_REG_PHYCTRL1 0x80
+#define MT6360_REG_PHYCTRL3 0x82
+#define MT6360_REG_PHYCTRL7 0x86
#define MT6360_REG_VCONNCTRL1 0x8C
#define MT6360_REG_MODECTRL2 0x8F
#define MT6360_REG_SWRESET 0xA0
@@ -22,6 +25,8 @@
#define MT6360_REG_DRPCTRL1 0xA2
#define MT6360_REG_DRPCTRL2 0xA3
#define MT6360_REG_I2CTORST 0xBF
+#define MT6360_REG_PHYCTRL11 0xCA
+#define MT6360_REG_RXCTRL1 0xCE
#define MT6360_REG_RXCTRL2 0xCF
#define MT6360_REG_CTDCTRL2 0xEC
@@ -106,6 +111,27 @@ static int mt6360_tcpc_init(struct tcpci *tcpci, struct tcpci_data *tdata)
if (ret)
return ret;
+ /* BMC PHY */
+ ret = mt6360_tcpc_write16(regmap, MT6360_REG_PHYCTRL1, 0x3A70);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(regmap, MT6360_REG_PHYCTRL3, 0x82);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(regmap, MT6360_REG_PHYCTRL7, 0x36);
+ if (ret)
+ return ret;
+
+ ret = mt6360_tcpc_write16(regmap, MT6360_REG_PHYCTRL11, 0x3C60);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(regmap, MT6360_REG_RXCTRL1, 0xE8);
+ if (ret)
+ return ret;
+
/* Set shipping mode off, AUTOIDLE on */
return regmap_write(regmap, MT6360_REG_MODECTRL2, 0x7A);
}
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index 79001301b383..e0de44000d92 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -161,6 +161,7 @@ struct mlx5_vdpa_net {
struct mlx5_flow_handle *rx_rule_mcast;
bool setup;
u32 cur_num_vqs;
+ u32 rqt_size;
struct notifier_block nb;
struct vdpa_callback config_cb;
struct mlx5_vdpa_wq_ent cvq_ent;
@@ -204,17 +205,12 @@ static __virtio16 cpu_to_mlx5vdpa16(struct mlx5_vdpa_dev *mvdev, u16 val)
return __cpu_to_virtio16(mlx5_vdpa_is_little_endian(mvdev), val);
}
-static inline u32 mlx5_vdpa_max_qps(int max_vqs)
-{
- return max_vqs / 2;
-}
-
static u16 ctrl_vq_idx(struct mlx5_vdpa_dev *mvdev)
{
if (!(mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_MQ)))
return 2;
- return 2 * mlx5_vdpa_max_qps(mvdev->max_vqs);
+ return mvdev->max_vqs;
}
static bool is_ctrl_vq_idx(struct mlx5_vdpa_dev *mvdev, u16 idx)
@@ -1236,25 +1232,13 @@ static void teardown_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *
static int create_rqt(struct mlx5_vdpa_net *ndev)
{
__be32 *list;
- int max_rqt;
void *rqtc;
int inlen;
void *in;
int i, j;
int err;
- int num;
-
- if (!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_NET_F_MQ)))
- num = 1;
- else
- num = ndev->cur_num_vqs / 2;
- max_rqt = min_t(int, roundup_pow_of_two(num),
- 1 << MLX5_CAP_GEN(ndev->mvdev.mdev, log_max_rqt_size));
- if (max_rqt < 1)
- return -EOPNOTSUPP;
-
- inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + max_rqt * MLX5_ST_SZ_BYTES(rq_num);
+ inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + ndev->rqt_size * MLX5_ST_SZ_BYTES(rq_num);
in = kzalloc(inlen, GFP_KERNEL);
if (!in)
return -ENOMEM;
@@ -1263,12 +1247,12 @@ static int create_rqt(struct mlx5_vdpa_net *ndev)
rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
MLX5_SET(rqtc, rqtc, list_q_type, MLX5_RQTC_LIST_Q_TYPE_VIRTIO_NET_Q);
- MLX5_SET(rqtc, rqtc, rqt_max_size, max_rqt);
+ MLX5_SET(rqtc, rqtc, rqt_max_size, ndev->rqt_size);
list = MLX5_ADDR_OF(rqtc, rqtc, rq_num[0]);
- for (i = 0, j = 0; i < max_rqt; i++, j += 2)
- list[i] = cpu_to_be32(ndev->vqs[j % (2 * num)].virtq_id);
+ for (i = 0, j = 0; i < ndev->rqt_size; i++, j += 2)
+ list[i] = cpu_to_be32(ndev->vqs[j % ndev->cur_num_vqs].virtq_id);
- MLX5_SET(rqtc, rqtc, rqt_actual_size, max_rqt);
+ MLX5_SET(rqtc, rqtc, rqt_actual_size, ndev->rqt_size);
err = mlx5_vdpa_create_rqt(&ndev->mvdev, in, inlen, &ndev->res.rqtn);
kfree(in);
if (err)
@@ -1282,19 +1266,13 @@ static int create_rqt(struct mlx5_vdpa_net *ndev)
static int modify_rqt(struct mlx5_vdpa_net *ndev, int num)
{
__be32 *list;
- int max_rqt;
void *rqtc;
int inlen;
void *in;
int i, j;
int err;
- max_rqt = min_t(int, roundup_pow_of_two(ndev->cur_num_vqs / 2),
- 1 << MLX5_CAP_GEN(ndev->mvdev.mdev, log_max_rqt_size));
- if (max_rqt < 1)
- return -EOPNOTSUPP;
-
- inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + max_rqt * MLX5_ST_SZ_BYTES(rq_num);
+ inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + ndev->rqt_size * MLX5_ST_SZ_BYTES(rq_num);
in = kzalloc(inlen, GFP_KERNEL);
if (!in)
return -ENOMEM;
@@ -1305,10 +1283,10 @@ static int modify_rqt(struct mlx5_vdpa_net *ndev, int num)
MLX5_SET(rqtc, rqtc, list_q_type, MLX5_RQTC_LIST_Q_TYPE_VIRTIO_NET_Q);
list = MLX5_ADDR_OF(rqtc, rqtc, rq_num[0]);
- for (i = 0, j = 0; i < max_rqt; i++, j += 2)
+ for (i = 0, j = 0; i < ndev->rqt_size; i++, j += 2)
list[i] = cpu_to_be32(ndev->vqs[j % num].virtq_id);
- MLX5_SET(rqtc, rqtc, rqt_actual_size, max_rqt);
+ MLX5_SET(rqtc, rqtc, rqt_actual_size, ndev->rqt_size);
err = mlx5_vdpa_modify_rqt(&ndev->mvdev, in, inlen, ndev->res.rqtn);
kfree(in);
if (err)
@@ -1625,7 +1603,7 @@ static virtio_net_ctrl_ack handle_ctrl_mq(struct mlx5_vdpa_dev *mvdev, u8 cmd)
newqps = mlx5vdpa16_to_cpu(mvdev, mq.virtqueue_pairs);
if (newqps < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
- newqps > mlx5_vdpa_max_qps(mvdev->max_vqs))
+ newqps > ndev->rqt_size)
break;
if (ndev->cur_num_vqs == 2 * newqps) {
@@ -1989,7 +1967,7 @@ static int setup_virtqueues(struct mlx5_vdpa_dev *mvdev)
int err;
int i;
- for (i = 0; i < 2 * mlx5_vdpa_max_qps(mvdev->max_vqs); i++) {
+ for (i = 0; i < mvdev->max_vqs; i++) {
err = setup_vq(ndev, &ndev->vqs[i]);
if (err)
goto err_vq;
@@ -2060,9 +2038,11 @@ static int mlx5_vdpa_set_driver_features(struct vdpa_device *vdev, u64 features)
ndev->mvdev.actual_features = features & ndev->mvdev.mlx_features;
if (ndev->mvdev.actual_features & BIT_ULL(VIRTIO_NET_F_MQ))
- ndev->cur_num_vqs = 2 * mlx5vdpa16_to_cpu(mvdev, ndev->config.max_virtqueue_pairs);
+ ndev->rqt_size = mlx5vdpa16_to_cpu(mvdev, ndev->config.max_virtqueue_pairs);
else
- ndev->cur_num_vqs = 2;
+ ndev->rqt_size = 1;
+
+ ndev->cur_num_vqs = 2 * ndev->rqt_size;
update_cvq_info(mvdev);
return err;
@@ -2529,7 +2509,7 @@ static void init_mvqs(struct mlx5_vdpa_net *ndev)
struct mlx5_vdpa_virtqueue *mvq;
int i;
- for (i = 0; i < 2 * mlx5_vdpa_max_qps(ndev->mvdev.max_vqs); ++i) {
+ for (i = 0; i < ndev->mvdev.max_vqs; ++i) {
mvq = &ndev->vqs[i];
memset(mvq, 0, offsetof(struct mlx5_vdpa_virtqueue, ri));
mvq->index = i;
@@ -2671,7 +2651,8 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name,
return -EOPNOTSUPP;
}
- max_vqs = MLX5_CAP_DEV_VDPA_EMULATION(mdev, max_num_virtio_queues);
+ max_vqs = min_t(int, MLX5_CAP_DEV_VDPA_EMULATION(mdev, max_num_virtio_queues),
+ 1 << MLX5_CAP_GEN(mdev, log_max_rqt_size));
if (max_vqs < 2) {
dev_warn(mdev->device,
"%d virtqueues are supported. At least 2 are required\n",
@@ -2742,7 +2723,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name,
ndev->mvdev.mlx_features |= BIT_ULL(VIRTIO_NET_F_MAC);
}
- config->max_virtqueue_pairs = cpu_to_mlx5vdpa16(mvdev, mlx5_vdpa_max_qps(max_vqs));
+ config->max_virtqueue_pairs = cpu_to_mlx5vdpa16(mvdev, max_vqs / 2);
mvdev->vdev.dma_dev = &mdev->pdev->dev;
err = mlx5_vdpa_alloc_resources(&ndev->mvdev);
if (err)
@@ -2769,7 +2750,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name,
ndev->nb.notifier_call = event_handler;
mlx5_notifier_register(mdev, &ndev->nb);
mvdev->vdev.mdev = &mgtdev->mgtdev;
- err = _vdpa_register_device(&mvdev->vdev, 2 * mlx5_vdpa_max_qps(max_vqs) + 1);
+ err = _vdpa_register_device(&mvdev->vdev, max_vqs + 1);
if (err)
goto err_reg;
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 792ab5f23647..297b5db47454 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -1450,13 +1450,9 @@ err:
return ERR_PTR(r);
}
-static struct ptr_ring *get_tap_ptr_ring(int fd)
+static struct ptr_ring *get_tap_ptr_ring(struct file *file)
{
struct ptr_ring *ring;
- struct file *file = fget(fd);
-
- if (!file)
- return NULL;
ring = tun_get_tx_ring(file);
if (!IS_ERR(ring))
goto out;
@@ -1465,7 +1461,6 @@ static struct ptr_ring *get_tap_ptr_ring(int fd)
goto out;
ring = NULL;
out:
- fput(file);
return ring;
}
@@ -1552,8 +1547,12 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
r = vhost_net_enable_vq(n, vq);
if (r)
goto err_used;
- if (index == VHOST_NET_VQ_RX)
- nvq->rx_ring = get_tap_ptr_ring(fd);
+ if (index == VHOST_NET_VQ_RX) {
+ if (sock)
+ nvq->rx_ring = get_tap_ptr_ring(sock->file);
+ else
+ nvq->rx_ring = NULL;
+ }
oldubufs = nvq->ubufs;
nvq->ubufs = ubufs;
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 97eb0dee411c..a6bb0e438216 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1434,10 +1434,7 @@ fb_release(struct inode *inode, struct file *file)
__acquires(&info->lock)
__releases(&info->lock)
{
- struct fb_info * const info = file_fb_info(file);
-
- if (!info)
- return -ENODEV;
+ struct fb_info * const info = file->private_data;
lock_fb_info(info);
if (info->fbops->fb_release)
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index 26892940c213..82e31a2d845e 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -80,6 +80,10 @@ void framebuffer_release(struct fb_info *info)
{
if (!info)
return;
+
+ if (WARN_ON(refcount_read(&info->count)))
+ return;
+
kfree(info->apertures);
kfree(info);
}
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index ea42ba6445b2..b3d5f884c544 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -243,6 +243,10 @@ error:
static inline void efifb_show_boot_graphics(struct fb_info *info) {}
#endif
+/*
+ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
+ * of unregister_framebuffer() or fb_release(). Do any cleanup here.
+ */
static void efifb_destroy(struct fb_info *info)
{
if (efifb_pci_dev)
@@ -254,10 +258,13 @@ static void efifb_destroy(struct fb_info *info)
else
memunmap(info->screen_base);
}
+
if (request_mem_succeeded)
release_mem_region(info->apertures->ranges[0].base,
info->apertures->ranges[0].size);
fb_dealloc_cmap(&info->cmap);
+
+ framebuffer_release(info);
}
static const struct fb_ops efifb_ops = {
@@ -620,9 +627,9 @@ static int efifb_remove(struct platform_device *pdev)
{
struct fb_info *info = platform_get_drvdata(pdev);
+ /* efifb_destroy takes care of info cleanup */
unregister_framebuffer(info);
sysfs_remove_groups(&pdev->dev.kobj, efifb_groups);
- framebuffer_release(info);
return 0;
}
diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
index 94fc9c6d0411..2c198561c338 100644
--- a/drivers/video/fbdev/simplefb.c
+++ b/drivers/video/fbdev/simplefb.c
@@ -84,6 +84,10 @@ struct simplefb_par {
static void simplefb_clocks_destroy(struct simplefb_par *par);
static void simplefb_regulators_destroy(struct simplefb_par *par);
+/*
+ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
+ * of unregister_framebuffer() or fb_release(). Do any cleanup here.
+ */
static void simplefb_destroy(struct fb_info *info)
{
struct simplefb_par *par = info->par;
@@ -94,6 +98,8 @@ static void simplefb_destroy(struct fb_info *info)
if (info->screen_base)
iounmap(info->screen_base);
+ framebuffer_release(info);
+
if (mem)
release_mem_region(mem->start, resource_size(mem));
}
@@ -545,8 +551,8 @@ static int simplefb_remove(struct platform_device *pdev)
{
struct fb_info *info = platform_get_drvdata(pdev);
+ /* simplefb_destroy takes care of info cleanup */
unregister_framebuffer(info);
- framebuffer_release(info);
return 0;
}
diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c
index df6de5a9dd4c..e25e8de5ff67 100644
--- a/drivers/video/fbdev/vesafb.c
+++ b/drivers/video/fbdev/vesafb.c
@@ -179,6 +179,10 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
return err;
}
+/*
+ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
+ * of unregister_framebuffer() or fb_release(). Do any cleanup here.
+ */
static void vesafb_destroy(struct fb_info *info)
{
struct vesafb_par *par = info->par;
@@ -188,6 +192,8 @@ static void vesafb_destroy(struct fb_info *info)
if (info->screen_base)
iounmap(info->screen_base);
release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
+
+ framebuffer_release(info);
}
static struct fb_ops vesafb_ops = {
@@ -484,10 +490,10 @@ static int vesafb_remove(struct platform_device *pdev)
{
struct fb_info *info = platform_get_drvdata(pdev);
+ /* vesafb_destroy takes care of info cleanup */
unregister_framebuffer(info);
if (((struct vesafb_par *)(info->par))->region)
release_region(0x3c0, 32);
- framebuffer_release(info);
return 0;
}
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index aa25bffd4823..b6edcf89a429 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -85,7 +85,7 @@ static bool ceph_dirty_folio(struct address_space *mapping, struct folio *folio)
if (folio_test_dirty(folio)) {
dout("%p dirty_folio %p idx %lu -- already dirty\n",
mapping->host, folio, folio->index);
- BUG_ON(!folio_get_private(folio));
+ VM_BUG_ON_FOLIO(!folio_test_private(folio), folio);
return false;
}
@@ -122,7 +122,7 @@ static bool ceph_dirty_folio(struct address_space *mapping, struct folio *folio)
* Reference snap context in folio->private. Also set
* PagePrivate so that we get invalidate_folio callback.
*/
- BUG_ON(folio_get_private(folio));
+ VM_BUG_ON_FOLIO(folio_test_private(folio), folio);
folio_attach_private(folio, snapc);
return ceph_fscache_dirty_folio(mapping, folio);
@@ -150,7 +150,7 @@ static void ceph_invalidate_folio(struct folio *folio, size_t offset,
}
WARN_ON(!folio_test_locked(folio));
- if (folio_get_private(folio)) {
+ if (folio_test_private(folio)) {
dout("%p invalidate_folio idx %lu full dirty page\n",
inode, folio->index);
@@ -729,8 +729,11 @@ static void writepages_finish(struct ceph_osd_request *req)
/* clean all pages */
for (i = 0; i < req->r_num_ops; i++) {
- if (req->r_ops[i].op != CEPH_OSD_OP_WRITE)
+ if (req->r_ops[i].op != CEPH_OSD_OP_WRITE) {
+ pr_warn("%s incorrect op %d req %p index %d tid %llu\n",
+ __func__, req->r_ops[i].op, req, i, req->r_tid);
break;
+ }
osd_data = osd_req_op_extent_osd_data(req, i);
BUG_ON(osd_data->type != CEPH_OSD_DATA_TYPE_PAGES);
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 6c9e837aa1d3..8c8226c0feac 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -629,9 +629,15 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,
iinfo.change_attr = 1;
ceph_encode_timespec64(&iinfo.btime, &now);
- iinfo.xattr_len = ARRAY_SIZE(xattr_buf);
- iinfo.xattr_data = xattr_buf;
- memset(iinfo.xattr_data, 0, iinfo.xattr_len);
+ if (req->r_pagelist) {
+ iinfo.xattr_len = req->r_pagelist->length;
+ iinfo.xattr_data = req->r_pagelist->mapped_tail;
+ } else {
+ /* fake it */
+ iinfo.xattr_len = ARRAY_SIZE(xattr_buf);
+ iinfo.xattr_data = xattr_buf;
+ memset(iinfo.xattr_data, 0, iinfo.xattr_len);
+ }
in.ino = cpu_to_le64(vino.ino);
in.snapid = cpu_to_le64(CEPH_NOSNAP);
@@ -743,6 +749,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
err = ceph_security_init_secctx(dentry, mode, &as_ctx);
if (err < 0)
goto out_ctx;
+ /* Async create can't handle more than a page of xattrs */
+ if (as_ctx.pagelist &&
+ !list_is_singular(&as_ctx.pagelist->head))
+ try_async = false;
} else if (!d_in_lookup(dentry)) {
/* If it's not being looked up, it's negative */
return -ENOENT;
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 39080b2d6cf8..b6697333bb2b 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -1153,13 +1153,12 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,
if (length != written && (iomap->flags & IOMAP_F_NEW)) {
/* Deallocate blocks that were just allocated. */
- loff_t blockmask = i_blocksize(inode) - 1;
- loff_t end = (pos + length) & ~blockmask;
+ loff_t hstart = round_up(pos + written, i_blocksize(inode));
+ loff_t hend = iomap->offset + iomap->length;
- pos = (pos + written + blockmask) & ~blockmask;
- if (pos < end) {
- truncate_pagecache_range(inode, pos, end - 1);
- punch_hole(ip, pos, end - pos);
+ if (hstart < hend) {
+ truncate_pagecache_range(inode, hstart, hend - 1);
+ punch_hole(ip, hstart, hend - hstart);
}
}
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 48f01323c37c..2556ae1f92ea 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -770,30 +770,27 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
return ret ? ret : ret1;
}
-static inline bool should_fault_in_pages(ssize_t ret, struct iov_iter *i,
+static inline bool should_fault_in_pages(struct iov_iter *i,
+ struct kiocb *iocb,
size_t *prev_count,
size_t *window_size)
{
size_t count = iov_iter_count(i);
size_t size, offs;
- if (likely(!count))
- return false;
- if (ret <= 0 && ret != -EFAULT)
+ if (!count)
return false;
if (!iter_is_iovec(i))
return false;
size = PAGE_SIZE;
- offs = offset_in_page(i->iov[0].iov_base + i->iov_offset);
+ offs = offset_in_page(iocb->ki_pos);
if (*prev_count != count || !*window_size) {
size_t nr_dirtied;
- size = ALIGN(offs + count, PAGE_SIZE);
- size = min_t(size_t, size, SZ_1M);
nr_dirtied = max(current->nr_dirtied_pause -
current->nr_dirtied, 8);
- size = min(size, nr_dirtied << PAGE_SHIFT);
+ size = min_t(size_t, SZ_1M, nr_dirtied << PAGE_SHIFT);
}
*prev_count = count;
@@ -807,7 +804,7 @@ static ssize_t gfs2_file_direct_read(struct kiocb *iocb, struct iov_iter *to,
struct file *file = iocb->ki_filp;
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
size_t prev_count = 0, window_size = 0;
- size_t written = 0;
+ size_t read = 0;
ssize_t ret;
/*
@@ -835,35 +832,31 @@ retry:
ret = gfs2_glock_nq(gh);
if (ret)
goto out_uninit;
-retry_under_glock:
pagefault_disable();
to->nofault = true;
ret = iomap_dio_rw(iocb, to, &gfs2_iomap_ops, NULL,
- IOMAP_DIO_PARTIAL, written);
+ IOMAP_DIO_PARTIAL, read);
to->nofault = false;
pagefault_enable();
+ if (ret <= 0 && ret != -EFAULT)
+ goto out_unlock;
if (ret > 0)
- written = ret;
-
- if (should_fault_in_pages(ret, to, &prev_count, &window_size)) {
- size_t leftover;
+ read = ret;
- gfs2_holder_allow_demote(gh);
- leftover = fault_in_iov_iter_writeable(to, window_size);
- gfs2_holder_disallow_demote(gh);
- if (leftover != window_size) {
- if (gfs2_holder_queued(gh))
- goto retry_under_glock;
+ if (should_fault_in_pages(to, iocb, &prev_count, &window_size)) {
+ gfs2_glock_dq(gh);
+ window_size -= fault_in_iov_iter_writeable(to, window_size);
+ if (window_size)
goto retry;
- }
}
+out_unlock:
if (gfs2_holder_queued(gh))
gfs2_glock_dq(gh);
out_uninit:
gfs2_holder_uninit(gh);
if (ret < 0)
return ret;
- return written;
+ return read;
}
static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
@@ -873,7 +866,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
struct inode *inode = file->f_mapping->host;
struct gfs2_inode *ip = GFS2_I(inode);
size_t prev_count = 0, window_size = 0;
- size_t read = 0;
+ size_t written = 0;
ssize_t ret;
/*
@@ -901,39 +894,35 @@ retry:
goto out_uninit;
/* Silently fall back to buffered I/O when writing beyond EOF */
if (iocb->ki_pos + iov_iter_count(from) > i_size_read(&ip->i_inode))
- goto out;
-retry_under_glock:
+ goto out_unlock;
from->nofault = true;
ret = iomap_dio_rw(iocb, from, &gfs2_iomap_ops, NULL,
- IOMAP_DIO_PARTIAL, read);
+ IOMAP_DIO_PARTIAL, written);
from->nofault = false;
-
- if (ret == -ENOTBLK)
- ret = 0;
+ if (ret <= 0) {
+ if (ret == -ENOTBLK)
+ ret = 0;
+ if (ret != -EFAULT)
+ goto out_unlock;
+ }
if (ret > 0)
- read = ret;
-
- if (should_fault_in_pages(ret, from, &prev_count, &window_size)) {
- size_t leftover;
+ written = ret;
- gfs2_holder_allow_demote(gh);
- leftover = fault_in_iov_iter_readable(from, window_size);
- gfs2_holder_disallow_demote(gh);
- if (leftover != window_size) {
- if (gfs2_holder_queued(gh))
- goto retry_under_glock;
+ if (should_fault_in_pages(from, iocb, &prev_count, &window_size)) {
+ gfs2_glock_dq(gh);
+ window_size -= fault_in_iov_iter_readable(from, window_size);
+ if (window_size)
goto retry;
- }
}
-out:
+out_unlock:
if (gfs2_holder_queued(gh))
gfs2_glock_dq(gh);
out_uninit:
gfs2_holder_uninit(gh);
if (ret < 0)
return ret;
- return read;
+ return written;
}
static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
@@ -941,7 +930,7 @@ static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
struct gfs2_inode *ip;
struct gfs2_holder gh;
size_t prev_count = 0, window_size = 0;
- size_t written = 0;
+ size_t read = 0;
ssize_t ret;
/*
@@ -962,7 +951,7 @@ static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
if (ret >= 0) {
if (!iov_iter_count(to))
return ret;
- written = ret;
+ read = ret;
} else if (ret != -EFAULT) {
if (ret != -EAGAIN)
return ret;
@@ -975,30 +964,26 @@ retry:
ret = gfs2_glock_nq(&gh);
if (ret)
goto out_uninit;
-retry_under_glock:
pagefault_disable();
ret = generic_file_read_iter(iocb, to);
pagefault_enable();
+ if (ret <= 0 && ret != -EFAULT)
+ goto out_unlock;
if (ret > 0)
- written += ret;
-
- if (should_fault_in_pages(ret, to, &prev_count, &window_size)) {
- size_t leftover;
+ read += ret;
- gfs2_holder_allow_demote(&gh);
- leftover = fault_in_iov_iter_writeable(to, window_size);
- gfs2_holder_disallow_demote(&gh);
- if (leftover != window_size) {
- if (gfs2_holder_queued(&gh))
- goto retry_under_glock;
+ if (should_fault_in_pages(to, iocb, &prev_count, &window_size)) {
+ gfs2_glock_dq(&gh);
+ window_size -= fault_in_iov_iter_writeable(to, window_size);
+ if (window_size)
goto retry;
- }
}
+out_unlock:
if (gfs2_holder_queued(&gh))
gfs2_glock_dq(&gh);
out_uninit:
gfs2_holder_uninit(&gh);
- return written ? written : ret;
+ return read ? read : ret;
}
static ssize_t gfs2_file_buffered_write(struct kiocb *iocb,
@@ -1012,7 +997,7 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb,
struct gfs2_holder *statfs_gh = NULL;
size_t prev_count = 0, window_size = 0;
size_t orig_count = iov_iter_count(from);
- size_t read = 0;
+ size_t written = 0;
ssize_t ret;
/*
@@ -1030,10 +1015,18 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb,
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, gh);
retry:
+ if (should_fault_in_pages(from, iocb, &prev_count, &window_size)) {
+ window_size -= fault_in_iov_iter_readable(from, window_size);
+ if (!window_size) {
+ ret = -EFAULT;
+ goto out_uninit;
+ }
+ from->count = min(from->count, window_size);
+ }
ret = gfs2_glock_nq(gh);
if (ret)
goto out_uninit;
-retry_under_glock:
+
if (inode == sdp->sd_rindex) {
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
@@ -1050,25 +1043,19 @@ retry_under_glock:
current->backing_dev_info = NULL;
if (ret > 0) {
iocb->ki_pos += ret;
- read += ret;
+ written += ret;
}
if (inode == sdp->sd_rindex)
gfs2_glock_dq_uninit(statfs_gh);
- from->count = orig_count - read;
- if (should_fault_in_pages(ret, from, &prev_count, &window_size)) {
- size_t leftover;
-
- gfs2_holder_allow_demote(gh);
- leftover = fault_in_iov_iter_readable(from, window_size);
- gfs2_holder_disallow_demote(gh);
- if (leftover != window_size) {
- from->count = min(from->count, window_size - leftover);
- if (gfs2_holder_queued(gh))
- goto retry_under_glock;
- goto retry;
- }
+ if (ret <= 0 && ret != -EFAULT)
+ goto out_unlock;
+
+ from->count = orig_count - written;
+ if (should_fault_in_pages(from, iocb, &prev_count, &window_size)) {
+ gfs2_glock_dq(gh);
+ goto retry;
}
out_unlock:
if (gfs2_holder_queued(gh))
@@ -1077,8 +1064,8 @@ out_uninit:
gfs2_holder_uninit(gh);
if (statfs_gh)
kfree(statfs_gh);
- from->count = orig_count - read;
- return read ? read : ret;
+ from->count = orig_count - written;
+ return written ? written : ret;
}
/**
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 91de361ea9ab..e0823f58f795 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -4481,6 +4481,9 @@ done:
if (ret < 0)
req_set_fail(req);
__io_req_complete(req, issue_flags, ret, 0);
+ /* put file to avoid an attempt to IOPOLL the req */
+ io_put_file(req->file);
+ req->file = NULL;
return 0;
}
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index e2d59bb5e6bb..9a16897e8dc6 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -517,7 +517,7 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
if (result.negated)
ctx->flags &= ~NFS_MOUNT_SOFTREVAL;
else
- ctx->flags &= NFS_MOUNT_SOFTREVAL;
+ ctx->flags |= NFS_MOUNT_SOFTREVAL;
break;
case Opt_posix:
if (result.negated)
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 172c86270b31..913bef0d2a36 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -72,7 +72,7 @@ out:
return 0;
}
-static int seq_fdinfo_open(struct inode *inode, struct file *file)
+static int proc_fdinfo_access_allowed(struct inode *inode)
{
bool allowed = false;
struct task_struct *task = get_proc_task(inode);
@@ -86,6 +86,16 @@ static int seq_fdinfo_open(struct inode *inode, struct file *file)
if (!allowed)
return -EACCES;
+ return 0;
+}
+
+static int seq_fdinfo_open(struct inode *inode, struct file *file)
+{
+ int ret = proc_fdinfo_access_allowed(inode);
+
+ if (ret)
+ return ret;
+
return single_open(file, seq_show, inode);
}
@@ -348,12 +358,23 @@ static int proc_readfdinfo(struct file *file, struct dir_context *ctx)
proc_fdinfo_instantiate);
}
+static int proc_open_fdinfo(struct inode *inode, struct file *file)
+{
+ int ret = proc_fdinfo_access_allowed(inode);
+
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
const struct inode_operations proc_fdinfo_inode_operations = {
.lookup = proc_lookupfdinfo,
.setattr = proc_setattr,
};
const struct file_operations proc_fdinfo_operations = {
+ .open = proc_open_fdinfo,
.read = generic_read_dir,
.iterate_shared = proc_readfdinfo,
.llseek = generic_file_llseek,
diff --git a/include/linux/audit.h b/include/linux/audit.h
index d06134ac6245..cece70231138 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -339,7 +339,7 @@ static inline void audit_uring_entry(u8 op)
}
static inline void audit_uring_exit(int success, long code)
{
- if (unlikely(!audit_dummy_context()))
+ if (unlikely(audit_context()))
__audit_uring_exit(success, code);
}
static inline void audit_syscall_entry(int major, unsigned long a0,
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index c2ea47f30046..e22dc03c850e 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -17,7 +17,6 @@
#include <linux/can.h>
#include <linux/can/bittiming.h>
#include <linux/can/error.h>
-#include <linux/can/led.h>
#include <linux/can/length.h>
#include <linux/can/netlink.h>
#include <linux/can/skb.h>
@@ -85,15 +84,6 @@ struct can_priv {
int (*do_get_berr_counter)(const struct net_device *dev,
struct can_berr_counter *bec);
int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
-
-#ifdef CONFIG_CAN_LEDS
- struct led_trigger *tx_led_trig;
- char tx_led_trig_name[CAN_LED_NAME_SZ];
- struct led_trigger *rx_led_trig;
- char rx_led_trig_name[CAN_LED_NAME_SZ];
- struct led_trigger *rxtx_led_trig;
- char rxtx_led_trig_name[CAN_LED_NAME_SZ];
-#endif
};
static inline bool can_tdc_is_enabled(const struct can_priv *priv)
diff --git a/include/linux/can/led.h b/include/linux/can/led.h
deleted file mode 100644
index 7c3cfd798c56..000000000000
--- a/include/linux/can/led.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
- */
-
-#ifndef _CAN_LED_H
-#define _CAN_LED_H
-
-#include <linux/if.h>
-#include <linux/leds.h>
-#include <linux/netdevice.h>
-
-enum can_led_event {
- CAN_LED_EVENT_OPEN,
- CAN_LED_EVENT_STOP,
- CAN_LED_EVENT_TX,
- CAN_LED_EVENT_RX,
-};
-
-#ifdef CONFIG_CAN_LEDS
-
-/* keep space for interface name + "-tx"/"-rx"/"-rxtx"
- * suffix and null terminator
- */
-#define CAN_LED_NAME_SZ (IFNAMSIZ + 6)
-
-void can_led_event(struct net_device *netdev, enum can_led_event event);
-void devm_can_led_init(struct net_device *netdev);
-int __init can_led_notifier_init(void);
-void __exit can_led_notifier_exit(void);
-
-#else
-
-static inline void can_led_event(struct net_device *netdev,
- enum can_led_event event)
-{
-}
-static inline void devm_can_led_init(struct net_device *netdev)
-{
-}
-static inline int can_led_notifier_init(void)
-{
- return 0;
-}
-static inline void can_led_notifier_exit(void)
-{
-}
-
-#endif
-
-#endif /* !_CAN_LED_H */
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index ec5ca392eaa3..38c8203d52cb 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -145,6 +145,7 @@ struct inet6_skb_parm {
#define IP6SKB_L3SLAVE 64
#define IP6SKB_JUMBOGRAM 128
#define IP6SKB_SEG6 256
+#define IP6SKB_FAKEJUMBO 512
};
#if defined(CONFIG_NET_L3_MASTER_DEV)
diff --git a/include/linux/mfd/idt8a340_reg.h b/include/linux/mfd/idt8a340_reg.h
index a18c1539a152..0c706085c205 100644
--- a/include/linux/mfd/idt8a340_reg.h
+++ b/include/linux/mfd/idt8a340_reg.h
@@ -407,7 +407,7 @@
#define TOD_READ_PRIMARY_0 0xcc40
#define TOD_READ_PRIMARY_0_V520 0xcc50
/* 8-bit subns, 32-bit ns, 48-bit seconds */
-#define TOD_READ_PRIMARY 0x0000
+#define TOD_READ_PRIMARY_BASE 0x0000
/* Counter increments after TOD write is completed */
#define TOD_READ_PRIMARY_COUNTER 0x000b
/* Read trigger configuration */
@@ -424,6 +424,16 @@
#define TOD_READ_SECONDARY_0 0xcc90
#define TOD_READ_SECONDARY_0_V520 0xcca0
+/* 8-bit subns, 32-bit ns, 48-bit seconds */
+#define TOD_READ_SECONDARY_BASE 0x0000
+/* Counter increments after TOD write is completed */
+#define TOD_READ_SECONDARY_COUNTER 0x000b
+/* Read trigger configuration */
+#define TOD_READ_SECONDARY_SEL_CFG_0 0x000c
+/* Read trigger selection */
+#define TOD_READ_SECONDARY_CMD 0x000e
+#define TOD_READ_SECONDARY_CMD_V520 0x000f
+
#define TOD_READ_SECONDARY_1 0xcca0
#define TOD_READ_SECONDARY_1_V520 0xccb0
#define TOD_READ_SECONDARY_2 0xccb0
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index d6bac3976913..b064bc278f52 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -272,6 +272,8 @@ struct mlx5_cmd_stats {
u32 last_failed_errno;
/* last bad status returned by FW */
u8 last_failed_mbox_status;
+ /* last command failed syndrome returned by FW */
+ u32 last_failed_syndrome;
struct dentry *root;
/* protect command average calculations */
spinlock_t lock;
@@ -1051,9 +1053,14 @@ int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in,
int size_in, void *data_out, int size_out,
u16 reg_num, int arg, int write);
-int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db);
int mlx5_db_alloc_node(struct mlx5_core_dev *dev, struct mlx5_db *db,
int node);
+
+static inline int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db)
+{
+ return mlx5_db_alloc_node(dev, db, dev->priv.numa_node);
+}
+
void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db);
const char *mlx5_command_str(int command);
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 7bab3e51c61e..78b3d3465dd7 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -1359,7 +1359,7 @@ struct mlx5_ifc_cmd_hca_cap_bits {
u8 vhca_resource_manager[0x1];
u8 hca_cap_2[0x1];
- u8 reserved_at_21[0x1];
+ u8 create_lag_when_not_master_up[0x1];
u8 dtor[0x1];
u8 event_on_vhca_state_teardown_request[0x1];
u8 event_on_vhca_state_in_use[0x1];
@@ -10816,7 +10816,8 @@ struct mlx5_ifc_dcbx_param_bits {
enum {
MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY = 0,
- MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT,
+ MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT = 1,
+ MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_MPESW = 2,
};
struct mlx5_ifc_lagc_bits {
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 536321691c72..1ce91cb8074a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -910,7 +910,7 @@ struct net_device_path_stack {
struct net_device_path_ctx {
const struct net_device *dev;
- const u8 *daddr;
+ u8 daddr[ETH_ALEN];
int num_vlans;
struct {
@@ -2161,7 +2161,11 @@ struct net_device {
struct bpf_prog __rcu *xdp_prog;
unsigned long gro_flush_timeout;
int napi_defer_hard_irqs;
-#define GRO_MAX_SIZE 65536
+#define GRO_LEGACY_MAX_SIZE 65536u
+/* TCP minimal MSS is 8 (TCP_MIN_GSO_SIZE),
+ * and shinfo->gso_segs is a 16bit field.
+ */
+#define GRO_MAX_SIZE (8 * 65535u)
unsigned int gro_max_size;
rx_handler_func_t __rcu *rx_handler;
void __rcu *rx_handler_data;
@@ -2272,12 +2276,17 @@ struct net_device {
const struct rtnl_link_ops *rtnl_link_ops;
/* for setting kernel sock attribute on TCP connection setup */
-#define GSO_MAX_SIZE 65536
+#define GSO_MAX_SEGS 65535u
+#define GSO_LEGACY_MAX_SIZE 65536u
+/* TCP minimal MSS is 8 (TCP_MIN_GSO_SIZE),
+ * and shinfo->gso_segs is a 16bit field.
+ */
+#define GSO_MAX_SIZE (8 * GSO_MAX_SEGS)
+
unsigned int gso_max_size;
#define TSO_LEGACY_MAX_SIZE 65536
#define TSO_MAX_SIZE UINT_MAX
unsigned int tso_max_size;
-#define GSO_MAX_SEGS 65535
u16 gso_max_segs;
#define TSO_MAX_SEGS U16_MAX
u16 tso_max_segs;
@@ -3127,6 +3136,7 @@ struct softnet_data {
/* Another possibly contended cache line */
spinlock_t defer_lock ____cacheline_aligned_in_smp;
int defer_count;
+ int defer_ipi_scheduled;
struct sk_buff *defer_list;
call_single_data_t defer_csd;
};
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9d82a8b6c8f1..da96f0d3e753 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -510,7 +510,8 @@ enum skb_drop_reason {
(name = SKB_DROP_REASON_##reason)
#define SKB_DR_OR(name, reason) \
do { \
- if (name == SKB_DROP_REASON_NOT_SPECIFIED) \
+ if (name == SKB_DROP_REASON_NOT_SPECIFIED || \
+ name == SKB_NOT_DROPPED_YET) \
SKB_DR_SET(name, reason); \
} while (0)
@@ -1764,11 +1765,6 @@ static inline void skb_set_end_offset(struct sk_buff *skb, unsigned int offset)
}
#endif
-static inline unsigned int skb_data_area_size(struct sk_buff *skb)
-{
- return skb_end_pointer(skb) - skb->data;
-}
-
struct ubuf_info *msg_zerocopy_realloc(struct sock *sk, size_t size,
struct ubuf_info *uarg);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index db5149567305..90501404fa49 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -160,7 +160,7 @@ struct rpc_add_xprt_test {
#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9)
#define RPC_CLNT_CREATE_SOFTERR (1UL << 10)
#define RPC_CLNT_CREATE_REUSEPORT (1UL << 11)
-#define RPC_CLNT_CREATE_IGNORE_NULL_UNAVAIL (1UL << 12)
+#define RPC_CLNT_CREATE_CONNECTED (1UL << 12)
struct rpc_clnt *rpc_create(struct rpc_create_args *args);
struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 68713388b617..cc8a9880b9d6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1183,6 +1183,9 @@ struct cfg80211_mbssid_elems {
* Token (measurement type 11)
* @lci_len: LCI data length
* @civicloc_len: Civic location data length
+ * @he_bss_color: BSS Color settings
+ * @he_bss_color_valid: indicates whether bss color
+ * attribute is present in beacon data or not.
*/
struct cfg80211_beacon_data {
const u8 *head, *tail;
@@ -1202,6 +1205,8 @@ struct cfg80211_beacon_data {
size_t probe_resp_len;
size_t lci_len;
size_t civicloc_len;
+ struct cfg80211_he_bss_color he_bss_color;
+ bool he_bss_color_valid;
};
struct mac_address {
@@ -1292,7 +1297,6 @@ struct cfg80211_unsol_bcast_probe_resp {
* @sae_h2e_required: stations must support direct H2E technique in SAE
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
* @he_obss_pd: OBSS Packet Detection settings
- * @he_bss_color: BSS Color settings
* @he_oper: HE operation IE (or %NULL if HE isn't enabled)
* @fils_discovery: FILS discovery transmission parameters
* @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
@@ -1326,7 +1330,6 @@ struct cfg80211_ap_settings {
bool twt_responder;
u32 flags;
struct ieee80211_he_obss_pd he_obss_pd;
- struct cfg80211_he_bss_color he_bss_color;
struct cfg80211_fils_discovery fils_discovery;
struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
struct cfg80211_mbssid_config mbssid_config;
@@ -2735,6 +2738,7 @@ struct cfg80211_auth_request {
* userspace if this flag is set. Only applicable for cfg80211_connect()
* request (connect callback).
* @ASSOC_REQ_DISABLE_HE: Disable HE
+ * @ASSOC_REQ_DISABLE_EHT: Disable EHT
*/
enum cfg80211_assoc_req_flags {
ASSOC_REQ_DISABLE_HT = BIT(0),
@@ -2742,6 +2746,7 @@ enum cfg80211_assoc_req_flags {
ASSOC_REQ_USE_RRM = BIT(2),
CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3),
ASSOC_REQ_DISABLE_HE = BIT(4),
+ ASSOC_REQ_DISABLE_EHT = BIT(5),
};
/**
@@ -5549,8 +5554,6 @@ static inline void wiphy_unlock(struct wiphy *wiphy)
* @conn_owner_nlportid: (private) connection owner socket port ID
* @disconnect_wk: (private) auto-disconnect work
* @disconnect_bssid: (private) the BSSID to use for auto-disconnect
- * @ibss_fixed: (private) IBSS is using fixed BSSID
- * @ibss_dfs_possible: (private) IBSS may change to a DFS channel
* @event_list: (private) list for internal event processing
* @event_lock: (private) lock for event list
* @owner_nlportid: (private) owner socket port ID
@@ -5599,9 +5602,6 @@ struct wireless_dev {
struct cfg80211_chan_def preset_chandef;
struct cfg80211_chan_def chandef;
- bool ibss_fixed;
- bool ibss_dfs_possible;
-
bool ps;
int ps_timeout;
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 81b965953036..f259e1ae14ba 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -103,15 +103,25 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
const int dif);
int inet6_hash(struct sock *sk);
-#endif /* IS_ENABLED(CONFIG_IPV6) */
-#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif, __sdif) \
- (((__sk)->sk_portpair == (__ports)) && \
- ((__sk)->sk_family == AF_INET6) && \
- ipv6_addr_equal(&(__sk)->sk_v6_daddr, (__saddr)) && \
- ipv6_addr_equal(&(__sk)->sk_v6_rcv_saddr, (__daddr)) && \
- (((__sk)->sk_bound_dev_if == (__dif)) || \
- ((__sk)->sk_bound_dev_if == (__sdif))) && \
- net_eq(sock_net(__sk), (__net)))
+static inline bool inet6_match(struct net *net, const struct sock *sk,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ const __portpair ports,
+ const int dif, const int sdif)
+{
+ int bound_dev_if;
+
+ if (!net_eq(sock_net(sk), net) ||
+ sk->sk_family != AF_INET6 ||
+ sk->sk_portpair != ports ||
+ !ipv6_addr_equal(&sk->sk_v6_daddr, saddr) ||
+ !ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr))
+ return false;
+
+ bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
+ return bound_dev_if == dif || bound_dev_if == sdif;
+}
+#endif /* IS_ENABLED(CONFIG_IPV6) */
#endif /* _INET6_HASHTABLES_H */
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 59d72024ad1d..ebfa3df6f8dc 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -267,7 +267,7 @@ static inline struct sock *inet_lookup_listener(struct net *net,
((__force __u64)(__be32)(__saddr)))
#endif /* __BIG_ENDIAN */
-static inline bool INET_MATCH(struct net *net, const struct sock *sk,
+static inline bool inet_match(struct net *net, const struct sock *sk,
const __addrpair cookie, const __portpair ports,
int dif, int sdif)
{
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 234d70ae5f4c..c1b5dcd6597c 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -116,14 +116,15 @@ static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb)
static inline int inet_request_bound_dev_if(const struct sock *sk,
struct sk_buff *skb)
{
+ int bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
#ifdef CONFIG_NET_L3_MASTER_DEV
struct net *net = sock_net(sk);
- if (!sk->sk_bound_dev_if && net->ipv4.sysctl_tcp_l3mdev_accept)
+ if (!bound_dev_if && net->ipv4.sysctl_tcp_l3mdev_accept)
return l3mdev_master_ifindex_by_index(net, skb->skb_iif);
#endif
- return sk->sk_bound_dev_if;
+ return bound_dev_if;
}
static inline int inet_sk_bound_l3mdev(const struct sock *sk)
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 463ae5d33eb0..5b47545f22d3 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -71,7 +71,6 @@ struct inet_timewait_sock {
tw_tos : 8;
u32 tw_txhash;
u32 tw_priority;
- u32 tw_bslot; /* bind bucket slot */
struct timer_list tw_timer;
struct inet_bind_bucket *tw_tb;
};
@@ -110,6 +109,8 @@ static inline void inet_twsk_reschedule(struct inet_timewait_sock *tw, int timeo
void inet_twsk_deschedule_put(struct inet_timewait_sock *tw);
+void inet_twsk_purge(struct inet_hashinfo *hashinfo, int family);
+
static inline
struct net *twsk_net(const struct inet_timewait_sock *twsk)
{
diff --git a/include/net/ip.h b/include/net/ip.h
index 3984f2c39c4b..26fffda78cca 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -56,6 +56,7 @@ struct inet_skb_parm {
#define IPSKB_DOREDIRECT BIT(5)
#define IPSKB_FRAG_PMTU BIT(6)
#define IPSKB_L3SLAVE BIT(7)
+#define IPSKB_NOPOLICY BIT(8)
u16 frag_max_size;
};
@@ -93,7 +94,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
ipcm->sockc.mark = inet->sk.sk_mark;
ipcm->sockc.tsflags = inet->sk.sk_tsflags;
- ipcm->oif = inet->sk.sk_bound_dev_if;
+ ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
ipcm->addr = inet->inet_saddr;
}
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 213612f1680c..5b38bf1a586b 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -151,6 +151,17 @@ struct frag_hdr {
__be32 identification;
};
+/*
+ * Jumbo payload option, as described in RFC 2675 2.
+ */
+struct hop_jumbo_hdr {
+ u8 nexthdr;
+ u8 hdrlen;
+ u8 tlv_type; /* IPV6_TLV_JUMBO, 0xC2 */
+ u8 tlv_len; /* 4 */
+ __be32 jumbo_payload_len;
+};
+
#define IP6_MF 0x0001
#define IP6_OFFSET 0xFFF8
@@ -456,6 +467,39 @@ bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb,
struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
struct ipv6_txoptions *opt);
+/* This helper is specialized for BIG TCP needs.
+ * It assumes the hop_jumbo_hdr will immediately follow the IPV6 header.
+ * It assumes headers are already in skb->head.
+ * Returns 0, or IPPROTO_TCP if a BIG TCP packet is there.
+ */
+static inline int ipv6_has_hopopt_jumbo(const struct sk_buff *skb)
+{
+ const struct hop_jumbo_hdr *jhdr;
+ const struct ipv6hdr *nhdr;
+
+ if (likely(skb->len <= GRO_LEGACY_MAX_SIZE))
+ return 0;
+
+ if (skb->protocol != htons(ETH_P_IPV6))
+ return 0;
+
+ if (skb_network_offset(skb) +
+ sizeof(struct ipv6hdr) +
+ sizeof(struct hop_jumbo_hdr) > skb_headlen(skb))
+ return 0;
+
+ nhdr = ipv6_hdr(skb);
+
+ if (nhdr->nexthdr != NEXTHDR_HOP)
+ return 0;
+
+ jhdr = (const struct hop_jumbo_hdr *) (nhdr + 1);
+ if (jhdr->tlv_type != IPV6_TLV_JUMBO || jhdr->hdrlen != 0 ||
+ jhdr->nexthdr != IPPROTO_TCP)
+ return 0;
+ return jhdr->nexthdr;
+}
+
static inline bool ipv6_accept_ra(struct inet6_dev *idev)
{
/* If forwarding is enabled, RA are not accepted unless the special
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 75880fc70700..ebadb2103968 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -514,7 +514,6 @@ struct ieee80211_fils_discovery {
* to that BSS) that can change during the lifetime of the BSS.
*
* @htc_trig_based_pkt_ext: default PE in 4us units, if BSS supports HE
- * @multi_sta_back_32bit: supports BA bitmap of 32-bits in Multi-STA BACK
* @uora_exists: is the UORA element advertised by AP
* @ack_enabled: indicates support to receive a multi-TID that solicits either
* ACK, BACK or both
@@ -1144,20 +1143,41 @@ ieee80211_info_get_tx_time_est(struct ieee80211_tx_info *info)
return info->tx_time_est << 2;
}
+/***
+ * struct ieee80211_rate_status - mrr stage for status path
+ *
+ * This struct is used in struct ieee80211_tx_status to provide drivers a
+ * dynamic way to report about used rates and power levels per packet.
+ *
+ * @rate_idx The actual used rate.
+ * @try_count How often the rate was tried.
+ * @tx_power_idx An idx into the ieee80211_hw->tx_power_levels list of the
+ * corresponding wifi hardware. The idx shall point to the power level
+ * that was used when sending the packet.
+ */
+struct ieee80211_rate_status {
+ struct rate_info rate_idx;
+ u8 try_count;
+ u8 tx_power_idx;
+};
+
/**
* struct ieee80211_tx_status - extended tx status info for rate control
*
* @sta: Station that the packet was transmitted for
* @info: Basic tx status information
* @skb: Packet skb (can be NULL if not provided by the driver)
- * @rate: The TX rate that was used when sending the packet
+ * @rates: Mrr stages that were used when sending the packet
+ * @n_rates: Number of mrr stages (count of instances for @rates)
* @free_list: list where processed skbs are stored to be free'd by the driver
*/
struct ieee80211_tx_status {
struct ieee80211_sta *sta;
struct ieee80211_tx_info *info;
struct sk_buff *skb;
- struct rate_info *rate;
+ struct ieee80211_rate_status *rates;
+ u8 n_rates;
+
struct list_head *free_list;
};
@@ -1701,7 +1721,7 @@ enum ieee80211_offload_flags {
* these need to be set (or cleared) when the interface is added
* or, if supported by the driver, the interface type is changed
* at runtime, mac80211 will never touch this field
- * @offloaad_flags: hardware offload capabilities/flags for this interface.
+ * @offload_flags: hardware offload capabilities/flags for this interface.
* These are initialized by mac80211 before calling .add_interface,
* .change_interface or .update_vif_offload and updated by the driver
* within these ops, based on supported features or runtime change
@@ -2658,6 +2678,12 @@ enum ieee80211_hw_flags {
* refilling deficit of each TXQ.
*
* @max_mtu: the max mtu could be set.
+ *
+ * @tx_power_levels: a list of power levels supported by the wifi hardware.
+ * The power levels can be specified either as integer or fractions.
+ * The power level at idx 0 shall be the maximum positive power level.
+ *
+ * @max_txpwr_levels_idx: the maximum valid idx of 'tx_power_levels' list.
*/
struct ieee80211_hw {
struct ieee80211_conf conf;
@@ -2696,6 +2722,8 @@ struct ieee80211_hw {
u8 tx_sk_pacing_shift;
u8 weight_multiplier;
u32 max_mtu;
+ const s8 *tx_power_levels;
+ u8 max_txpwr_levels_idx;
};
static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw,
diff --git a/include/net/sock.h b/include/net/sock.h
index 01edfde4257d..72ca97ccb460 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2875,13 +2875,14 @@ static inline void sk_pacing_shift_update(struct sock *sk, int val)
*/
static inline bool sk_dev_equal_l3scope(struct sock *sk, int dif)
{
+ int bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
int mdif;
- if (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif)
+ if (!bound_dev_if || bound_dev_if == dif)
return true;
mdif = l3mdev_master_ifindex_by_index(sock_net(sk), dif);
- if (mdif && mdif == sk->sk_bound_dev_if)
+ if (mdif && mdif == bound_dev_if)
return true;
return false;
diff --git a/include/net/tls.h b/include/net/tls.h
index b59f0a63292b..8017f1703447 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -238,6 +238,7 @@ struct tls_context {
u8 tx_conf:3;
u8 rx_conf:3;
+ u8 zerocopy_sendfile:1;
int (*push_pending_record)(struct sock *sk, int flags);
void (*sk_write_space)(struct sock *sk);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 736c349de8bf..c39d910d4b45 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1097,6 +1097,18 @@ static inline bool __xfrm_check_nopolicy(struct net *net, struct sk_buff *skb,
return false;
}
+static inline bool __xfrm_check_dev_nopolicy(struct sk_buff *skb,
+ int dir, unsigned short family)
+{
+ if (dir != XFRM_POLICY_OUT && family == AF_INET) {
+ /* same dst may be used for traffic originating from
+ * devices with different policy settings.
+ */
+ return IPCB(skb)->flags & IPSKB_NOPOLICY;
+ }
+ return skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY);
+}
+
static inline int __xfrm_policy_check2(struct sock *sk, int dir,
struct sk_buff *skb,
unsigned int family, int reverse)
@@ -1108,7 +1120,7 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
return __xfrm_policy_check(sk, ndir, skb, family);
return __xfrm_check_nopolicy(net, skb, dir) ||
- (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) ||
+ __xfrm_check_dev_nopolicy(skb, dir, family) ||
__xfrm_policy_check(sk, ndir, skb, family);
}
diff --git a/include/trace/events/io_uring.h b/include/trace/events/io_uring.h
index cddf5b6fbeb4..80d2588a090c 100644
--- a/include/trace/events/io_uring.h
+++ b/include/trace/events/io_uring.h
@@ -147,7 +147,7 @@ TRACE_EVENT(io_uring_queue_async_work,
TP_PROTO(void *ctx, void * req, unsigned long long user_data, u8 opcode,
unsigned int flags, struct io_wq_work *work, int rw),
- TP_ARGS(ctx, req, user_data, flags, opcode, work, rw),
+ TP_ARGS(ctx, req, user_data, opcode, flags, work, rw),
TP_STRUCT__entry (
__field( void *, ctx )
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 65e786756321..fbb99a61f714 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -222,11 +222,11 @@ static inline long __trace_sched_switch_state(bool preempt,
TRACE_EVENT(sched_switch,
TP_PROTO(bool preempt,
- unsigned int prev_state,
struct task_struct *prev,
- struct task_struct *next),
+ struct task_struct *next,
+ unsigned int prev_state),
- TP_ARGS(preempt, prev_state, prev, next),
+ TP_ARGS(preempt, prev, next, prev_state),
TP_STRUCT__entry(
__array( char, prev_comm, TASK_COMM_LEN )
diff --git a/include/uapi/linux/can/isotp.h b/include/uapi/linux/can/isotp.h
index 590f8aea2b6d..439c982f7e81 100644
--- a/include/uapi/linux/can/isotp.h
+++ b/include/uapi/linux/can/isotp.h
@@ -124,18 +124,19 @@ struct can_isotp_ll_options {
/* flags for isotp behaviour */
-#define CAN_ISOTP_LISTEN_MODE 0x001 /* listen only (do not send FC) */
-#define CAN_ISOTP_EXTEND_ADDR 0x002 /* enable extended addressing */
-#define CAN_ISOTP_TX_PADDING 0x004 /* enable CAN frame padding tx path */
-#define CAN_ISOTP_RX_PADDING 0x008 /* enable CAN frame padding rx path */
-#define CAN_ISOTP_CHK_PAD_LEN 0x010 /* check received CAN frame padding */
-#define CAN_ISOTP_CHK_PAD_DATA 0x020 /* check received CAN frame padding */
-#define CAN_ISOTP_HALF_DUPLEX 0x040 /* half duplex error state handling */
-#define CAN_ISOTP_FORCE_TXSTMIN 0x080 /* ignore stmin from received FC */
-#define CAN_ISOTP_FORCE_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */
-#define CAN_ISOTP_RX_EXT_ADDR 0x200 /* different rx extended addressing */
-#define CAN_ISOTP_WAIT_TX_DONE 0x400 /* wait for tx completion */
-#define CAN_ISOTP_SF_BROADCAST 0x800 /* 1-to-N functional addressing */
+#define CAN_ISOTP_LISTEN_MODE 0x0001 /* listen only (do not send FC) */
+#define CAN_ISOTP_EXTEND_ADDR 0x0002 /* enable extended addressing */
+#define CAN_ISOTP_TX_PADDING 0x0004 /* enable CAN frame padding tx path */
+#define CAN_ISOTP_RX_PADDING 0x0008 /* enable CAN frame padding rx path */
+#define CAN_ISOTP_CHK_PAD_LEN 0x0010 /* check received CAN frame padding */
+#define CAN_ISOTP_CHK_PAD_DATA 0x0020 /* check received CAN frame padding */
+#define CAN_ISOTP_HALF_DUPLEX 0x0040 /* half duplex error state handling */
+#define CAN_ISOTP_FORCE_TXSTMIN 0x0080 /* ignore stmin from received FC */
+#define CAN_ISOTP_FORCE_RXSTMIN 0x0100 /* ignore CFs depending on rx stmin */
+#define CAN_ISOTP_RX_EXT_ADDR 0x0200 /* different rx extended addressing */
+#define CAN_ISOTP_WAIT_TX_DONE 0x0400 /* wait for tx completion */
+#define CAN_ISOTP_SF_BROADCAST 0x0800 /* 1-to-N functional addressing */
+#define CAN_ISOTP_CF_BROADCAST 0x1000 /* 1-to-N transmission w/o FC */
/* protocol machine default values */
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index d1e600816b82..5f58dcfe2787 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -368,6 +368,8 @@ enum {
IFLA_PARENT_DEV_NAME,
IFLA_PARENT_DEV_BUS_NAME,
IFLA_GRO_MAX_SIZE,
+ IFLA_TSO_MAX_SIZE,
+ IFLA_TSO_MAX_SEGS,
__IFLA_MAX
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 0568a79097b8..d9490e3062a7 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3175,6 +3175,8 @@ enum nl80211_attrs {
NL80211_ATTR_EHT_CAPABILITY,
+ NL80211_ATTR_DISABLE_EHT,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/include/uapi/linux/tls.h b/include/uapi/linux/tls.h
index 5f38be0ec0f3..ac39328eabe7 100644
--- a/include/uapi/linux/tls.h
+++ b/include/uapi/linux/tls.h
@@ -39,6 +39,7 @@
/* TLS socket options */
#define TLS_TX 1 /* Set transmit parameters */
#define TLS_RX 2 /* Set receive parameters */
+#define TLS_TX_ZEROCOPY_SENDFILE 3 /* transmit zerocopy sendfile */
/* Supported versions */
#define TLS_VERSION_MINOR(ver) ((ver) & 0xFF)
@@ -160,6 +161,7 @@ enum {
TLS_INFO_CIPHER,
TLS_INFO_TXCONF,
TLS_INFO_RXCONF,
+ TLS_INFO_ZC_SENDFILE,
__TLS_INFO_MAX,
};
#define TLS_INFO_MAX (__TLS_INFO_MAX - 1)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index ea2ee1181921..f3a2abd6d1a1 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1959,6 +1959,12 @@ void __audit_uring_exit(int success, long code)
{
struct audit_context *ctx = audit_context();
+ if (ctx->dummy) {
+ if (ctx->context != AUDIT_CTX_URING)
+ return;
+ goto out;
+ }
+
if (ctx->context == AUDIT_CTX_SYSCALL) {
/*
* NOTE: See the note in __audit_uring_entry() about the case
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 0099b87dd853..d323b180b0f3 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -701,7 +701,6 @@ EXPORT_SYMBOL_GPL(generic_handle_irq_safe);
*/
int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwirq)
{
- WARN_ON_ONCE(!in_hardirq());
return handle_irq_desc(irq_resolve_mapping(domain, hwirq));
}
EXPORT_SYMBOL_GPL(generic_handle_domain_irq);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 51efaabac3e4..d58c0389eb23 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6382,7 +6382,7 @@ static void __sched notrace __schedule(unsigned int sched_mode)
migrate_disable_switch(rq, prev);
psi_sched_switch(prev, next, !task_on_rq_queued(prev));
- trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev_state, prev, next);
+ trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next, prev_state);
/* Also unlocks the rq: */
rq = context_switch(rq, prev, next, &rf);
diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c
index 8f4fb328133a..a7e84c8543cb 100644
--- a/kernel/trace/fgraph.c
+++ b/kernel/trace/fgraph.c
@@ -404,9 +404,9 @@ free:
static void
ftrace_graph_probe_sched_switch(void *ignore, bool preempt,
- unsigned int prev_state,
struct task_struct *prev,
- struct task_struct *next)
+ struct task_struct *next,
+ unsigned int prev_state)
{
unsigned long long timestamp;
int index;
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 4f1d2f5e7263..af899b058c8d 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -7420,9 +7420,9 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops)
static void
ftrace_filter_pid_sched_switch_probe(void *data, bool preempt,
- unsigned int prev_state,
struct task_struct *prev,
- struct task_struct *next)
+ struct task_struct *next,
+ unsigned int prev_state)
{
struct trace_array *tr = data;
struct trace_pid_list *pid_list;
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index e11e167b7809..f97de82d1342 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -773,9 +773,9 @@ void trace_event_follow_fork(struct trace_array *tr, bool enable)
static void
event_filter_pid_sched_switch_probe_pre(void *data, bool preempt,
- unsigned int prev_state,
struct task_struct *prev,
- struct task_struct *next)
+ struct task_struct *next,
+ unsigned int prev_state)
{
struct trace_array *tr = data;
struct trace_pid_list *no_pid_list;
@@ -799,9 +799,9 @@ event_filter_pid_sched_switch_probe_pre(void *data, bool preempt,
static void
event_filter_pid_sched_switch_probe_post(void *data, bool preempt,
- unsigned int prev_state,
struct task_struct *prev,
- struct task_struct *next)
+ struct task_struct *next,
+ unsigned int prev_state)
{
struct trace_array *tr = data;
struct trace_pid_list *no_pid_list;
diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c
index e9ae1f33a7f0..afb92e2f0aea 100644
--- a/kernel/trace/trace_osnoise.c
+++ b/kernel/trace/trace_osnoise.c
@@ -1168,9 +1168,9 @@ thread_exit(struct osnoise_variables *osn_var, struct task_struct *t)
*/
static void
trace_sched_switch_callback(void *data, bool preempt,
- unsigned int prev_state,
struct task_struct *p,
- struct task_struct *n)
+ struct task_struct *n,
+ unsigned int prev_state)
{
struct osnoise_variables *osn_var = this_cpu_osn_var();
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c
index 45796d8bd4b2..c9ffdcfe622e 100644
--- a/kernel/trace/trace_sched_switch.c
+++ b/kernel/trace/trace_sched_switch.c
@@ -22,8 +22,8 @@ static DEFINE_MUTEX(sched_register_mutex);
static void
probe_sched_switch(void *ignore, bool preempt,
- unsigned int prev_state,
- struct task_struct *prev, struct task_struct *next)
+ struct task_struct *prev, struct task_struct *next,
+ unsigned int prev_state)
{
int flags;
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index 46429f9a96fa..330aee1c1a49 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -426,8 +426,8 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
static void notrace
probe_wakeup_sched_switch(void *ignore, bool preempt,
- unsigned int prev_state,
- struct task_struct *prev, struct task_struct *next)
+ struct task_struct *prev, struct task_struct *next,
+ unsigned int prev_state)
{
struct trace_array_cpu *data;
u64 T0, T1, delta;
diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c
index af9302141bcf..e5c5315da274 100644
--- a/lib/percpu-refcount.c
+++ b/lib/percpu-refcount.c
@@ -76,6 +76,7 @@ int percpu_ref_init(struct percpu_ref *ref, percpu_ref_func_t *release,
data = kzalloc(sizeof(*ref->data), gfp);
if (!data) {
free_percpu((void __percpu *)ref->percpu_count_ptr);
+ ref->percpu_count_ptr = 0;
return -ENOMEM;
}
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index c468fee595ff..910a138e9859 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2495,11 +2495,16 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
struct address_space *mapping = NULL;
int extra_pins, ret;
pgoff_t end;
+ bool is_hzp;
- VM_BUG_ON_PAGE(is_huge_zero_page(head), head);
VM_BUG_ON_PAGE(!PageLocked(head), head);
VM_BUG_ON_PAGE(!PageCompound(head), head);
+ is_hzp = is_huge_zero_page(head);
+ VM_WARN_ON_ONCE_PAGE(is_hzp, head);
+ if (is_hzp)
+ return -EBUSY;
+
if (PageWriteback(head))
return -EBUSY;
diff --git a/mm/kfence/core.c b/mm/kfence/core.c
index 9b2b5f56f4ae..11a954763be9 100644
--- a/mm/kfence/core.c
+++ b/mm/kfence/core.c
@@ -621,6 +621,16 @@ static bool __init kfence_init_pool_early(void)
* fails for the first page, and therefore expect addr==__kfence_pool in
* most failure cases.
*/
+ for (char *p = (char *)addr; p < __kfence_pool + KFENCE_POOL_SIZE; p += PAGE_SIZE) {
+ struct slab *slab = virt_to_slab(p);
+
+ if (!slab)
+ continue;
+#ifdef CONFIG_MEMCG
+ slab->memcg_data = 0;
+#endif
+ __folio_clear_slab(slab_folio(slab));
+ }
memblock_free_late(__pa(addr), KFENCE_POOL_SIZE - (addr - (unsigned long)__kfence_pool));
__kfence_pool = NULL;
return false;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 27760c19bad7..d4a4adcca01f 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1274,7 +1274,7 @@ try_again:
}
out:
if (ret == -EIO)
- dump_page(p, "hwpoison: unhandlable page");
+ pr_err("Memory failure: %#lx: unhandlable page.\n", page_to_pfn(p));
return ret;
}
@@ -1861,19 +1861,6 @@ try_again:
if (PageTransHuge(hpage)) {
/*
- * Bail out before SetPageHasHWPoisoned() if hpage is
- * huge_zero_page, although PG_has_hwpoisoned is not
- * checked in set_huge_zero_page().
- *
- * TODO: Handle memory failure of huge_zero_page thoroughly.
- */
- if (is_huge_zero_page(hpage)) {
- action_result(pfn, MF_MSG_UNSPLIT_THP, MF_IGNORED);
- res = -EBUSY;
- goto unlock_mutex;
- }
-
- /*
* The flag must be set after the refcount is bumped
* otherwise it may race with THP split.
* And the flag can't be set in get_hwpoison_page() since
diff --git a/mm/mremap.c b/mm/mremap.c
index 303d3290b938..0b93fac76851 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -947,7 +947,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
return -EINTR;
vma = vma_lookup(mm, addr);
if (!vma) {
- ret = EFAULT;
+ ret = -EFAULT;
goto out;
}
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
index d2a244e1c260..b80fccbac62a 100644
--- a/net/ax25/ax25_dev.c
+++ b/net/ax25/ax25_dev.c
@@ -115,23 +115,13 @@ void ax25_dev_device_down(struct net_device *dev)
if ((s = ax25_dev_list) == ax25_dev) {
ax25_dev_list = s->next;
- spin_unlock_bh(&ax25_dev_lock);
- ax25_dev_put(ax25_dev);
- dev->ax25_ptr = NULL;
- dev_put_track(dev, &ax25_dev->dev_tracker);
- ax25_dev_put(ax25_dev);
- return;
+ goto unlock_put;
}
while (s != NULL && s->next != NULL) {
if (s->next == ax25_dev) {
s->next = ax25_dev->next;
- spin_unlock_bh(&ax25_dev_lock);
- ax25_dev_put(ax25_dev);
- dev->ax25_ptr = NULL;
- dev_put_track(dev, &ax25_dev->dev_tracker);
- ax25_dev_put(ax25_dev);
- return;
+ goto unlock_put;
}
s = s->next;
@@ -139,6 +129,14 @@ void ax25_dev_device_down(struct net_device *dev)
spin_unlock_bh(&ax25_dev_lock);
dev->ax25_ptr = NULL;
ax25_dev_put(ax25_dev);
+ return;
+
+unlock_put:
+ spin_unlock_bh(&ax25_dev_lock);
+ ax25_dev_put(ax25_dev);
+ dev->ax25_ptr = NULL;
+ dev_put_track(dev, &ax25_dev->dev_tracker);
+ ax25_dev_put(ax25_dev);
}
int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index 8d54fef9a568..9b5a1f630bb0 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -1001,7 +1001,7 @@ static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb)
cb->pkt_len = skb->len;
} else {
if (__skb->wire_len < skb->len ||
- __skb->wire_len > GSO_MAX_SIZE)
+ __skb->wire_len > GSO_LEGACY_MAX_SIZE)
return -EINVAL;
cb->pkt_len = __skb->wire_len;
}
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 196417859c4a..68b3e850bcb9 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -39,6 +39,13 @@ static int br_pass_frame_up(struct sk_buff *skb)
dev_sw_netstats_rx_add(brdev, skb->len);
vg = br_vlan_group_rcu(br);
+
+ /* Reset the offload_fwd_mark because there could be a stacked
+ * bridge above, and it should not think this bridge it doing
+ * that bridge's work forwarding out its ports.
+ */
+ br_switchdev_frame_unmark(skb);
+
/* Bridge is just like any other port. Make sure the
* packet is allowed except in promisc mode when someone
* may be running packet capture.
diff --git a/net/can/isotp.c b/net/can/isotp.c
index 35a1ae61744c..43a27d19cdac 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -104,6 +104,7 @@ MODULE_ALIAS("can-proto-6");
#define FC_CONTENT_SZ 3 /* flow control content size in byte (FS/BS/STmin) */
#define ISOTP_CHECK_PADDING (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA)
+#define ISOTP_ALL_BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST)
/* Flow Status given in FC frame */
#define ISOTP_FC_CTS 0 /* clear to send */
@@ -159,6 +160,23 @@ static inline struct isotp_sock *isotp_sk(const struct sock *sk)
return (struct isotp_sock *)sk;
}
+static u32 isotp_bc_flags(struct isotp_sock *so)
+{
+ return so->opt.flags & ISOTP_ALL_BC_FLAGS;
+}
+
+static bool isotp_register_rxid(struct isotp_sock *so)
+{
+ /* no broadcast modes => register rx_id for FC frame reception */
+ return (isotp_bc_flags(so) == 0);
+}
+
+static bool isotp_register_txecho(struct isotp_sock *so)
+{
+ /* all modes but SF_BROADCAST register for tx echo skbs */
+ return (isotp_bc_flags(so) != CAN_ISOTP_SF_BROADCAST);
+}
+
static enum hrtimer_restart isotp_rx_timer_handler(struct hrtimer *hrtimer)
{
struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
@@ -803,7 +821,6 @@ static void isotp_create_fframe(struct canfd_frame *cf, struct isotp_sock *so,
cf->data[i] = so->tx.buf[so->tx.idx++];
so->tx.sn = 1;
- so->tx.state = ISOTP_WAIT_FIRST_FC;
}
static void isotp_rcv_echo(struct sk_buff *skb, void *data)
@@ -936,7 +953,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
off = (so->tx.ll_dl > CAN_MAX_DLEN) ? 1 : 0;
/* does the given data fit into a single frame for SF_BROADCAST? */
- if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) &&
+ if ((isotp_bc_flags(so) == CAN_ISOTP_SF_BROADCAST) &&
(size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) {
err = -EINVAL;
goto err_out_drop;
@@ -1000,12 +1017,41 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
/* don't enable wait queue for a single frame transmission */
wait_tx_done = 0;
} else {
- /* send first frame and wait for FC */
+ /* send first frame */
isotp_create_fframe(cf, so, ae);
- /* start timeout for FC */
- hrtimer_sec = 1;
+ if (isotp_bc_flags(so) == CAN_ISOTP_CF_BROADCAST) {
+ /* set timer for FC-less operation (STmin = 0) */
+ if (so->opt.flags & CAN_ISOTP_FORCE_TXSTMIN)
+ so->tx_gap = ktime_set(0, so->force_tx_stmin);
+ else
+ so->tx_gap = ktime_set(0, so->frame_txtime);
+
+ /* disable wait for FCs due to activated block size */
+ so->txfc.bs = 0;
+
+ /* cfecho should have been zero'ed by init */
+ if (so->cfecho)
+ pr_notice_once("can-isotp: no fc cfecho %08X\n",
+ so->cfecho);
+
+ /* set consecutive frame echo tag */
+ so->cfecho = *(u32 *)cf->data;
+
+ /* switch directly to ISOTP_SENDING state */
+ so->tx.state = ISOTP_SENDING;
+
+ /* start timeout for unlikely lost echo skb */
+ hrtimer_sec = 2;
+ } else {
+ /* standard flow control check */
+ so->tx.state = ISOTP_WAIT_FIRST_FC;
+
+ /* start timeout for FC */
+ hrtimer_sec = 1;
+ }
+
hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0),
HRTIMER_MODE_REL_SOFT);
}
@@ -1025,6 +1071,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (hrtimer_sec)
hrtimer_cancel(&so->txtimer);
+ /* reset consecutive frame echo tag */
+ so->cfecho = 0;
+
goto err_out_drop;
}
@@ -1120,15 +1169,17 @@ static int isotp_release(struct socket *sock)
lock_sock(sk);
/* remove current filters & unregister */
- if (so->bound && (!(so->opt.flags & CAN_ISOTP_SF_BROADCAST))) {
+ if (so->bound && isotp_register_txecho(so)) {
if (so->ifindex) {
struct net_device *dev;
dev = dev_get_by_index(net, so->ifindex);
if (dev) {
- can_rx_unregister(net, dev, so->rxid,
- SINGLE_MASK(so->rxid),
- isotp_rcv, sk);
+ if (isotp_register_rxid(so))
+ can_rx_unregister(net, dev, so->rxid,
+ SINGLE_MASK(so->rxid),
+ isotp_rcv, sk);
+
can_rx_unregister(net, dev, so->txid,
SINGLE_MASK(so->txid),
isotp_rcv_echo, sk);
@@ -1161,26 +1212,35 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
struct net *net = sock_net(sk);
int ifindex;
struct net_device *dev;
- canid_t tx_id, rx_id;
+ canid_t tx_id = addr->can_addr.tp.tx_id;
+ canid_t rx_id = addr->can_addr.tp.rx_id;
int err = 0;
int notify_enetdown = 0;
- int do_rx_reg = 1;
if (len < ISOTP_MIN_NAMELEN)
return -EINVAL;
- /* sanitize tx/rx CAN identifiers */
- tx_id = addr->can_addr.tp.tx_id;
+ /* sanitize tx CAN identifier */
if (tx_id & CAN_EFF_FLAG)
tx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
else
tx_id &= CAN_SFF_MASK;
- rx_id = addr->can_addr.tp.rx_id;
- if (rx_id & CAN_EFF_FLAG)
- rx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
- else
- rx_id &= CAN_SFF_MASK;
+ /* give feedback on wrong CAN-ID value */
+ if (tx_id != addr->can_addr.tp.tx_id)
+ return -EINVAL;
+
+ /* sanitize rx CAN identifier (if needed) */
+ if (isotp_register_rxid(so)) {
+ if (rx_id & CAN_EFF_FLAG)
+ rx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
+ else
+ rx_id &= CAN_SFF_MASK;
+
+ /* give feedback on wrong CAN-ID value */
+ if (rx_id != addr->can_addr.tp.rx_id)
+ return -EINVAL;
+ }
if (!addr->can_ifindex)
return -ENODEV;
@@ -1192,12 +1252,8 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
goto out;
}
- /* do not register frame reception for functional addressing */
- if (so->opt.flags & CAN_ISOTP_SF_BROADCAST)
- do_rx_reg = 0;
-
- /* do not validate rx address for functional addressing */
- if (do_rx_reg && rx_id == tx_id) {
+ /* ensure different CAN IDs when the rx_id is to be registered */
+ if (isotp_register_rxid(so) && rx_id == tx_id) {
err = -EADDRNOTAVAIL;
goto out;
}
@@ -1222,10 +1278,11 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
ifindex = dev->ifindex;
- if (do_rx_reg) {
+ if (isotp_register_rxid(so))
can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id),
isotp_rcv, sk, "isotp", sk);
+ if (isotp_register_txecho(so)) {
/* no consecutive frame echo skb in flight */
so->cfecho = 0;
@@ -1294,6 +1351,15 @@ static int isotp_setsockopt_locked(struct socket *sock, int level, int optname,
if (!(so->opt.flags & CAN_ISOTP_RX_EXT_ADDR))
so->opt.rx_ext_address = so->opt.ext_address;
+ /* these broadcast flags are not allowed together */
+ if (isotp_bc_flags(so) == ISOTP_ALL_BC_FLAGS) {
+ /* CAN_ISOTP_SF_BROADCAST is prioritized */
+ so->opt.flags &= ~CAN_ISOTP_CF_BROADCAST;
+
+ /* give user feedback on wrong config attempt */
+ ret = -EINVAL;
+ }
+
/* check for frame_txtime changes (0 => no changes) */
if (so->opt.frame_txtime) {
if (so->opt.frame_txtime == CAN_ISOTP_FRAME_TXTIME_ZERO)
@@ -1444,10 +1510,12 @@ static void isotp_notify(struct isotp_sock *so, unsigned long msg,
case NETDEV_UNREGISTER:
lock_sock(sk);
/* remove current filters & unregister */
- if (so->bound && (!(so->opt.flags & CAN_ISOTP_SF_BROADCAST))) {
- can_rx_unregister(dev_net(dev), dev, so->rxid,
- SINGLE_MASK(so->rxid),
- isotp_rcv, sk);
+ if (so->bound && isotp_register_txecho(so)) {
+ if (isotp_register_rxid(so))
+ can_rx_unregister(dev_net(dev), dev, so->rxid,
+ SINGLE_MASK(so->rxid),
+ isotp_rcv, sk);
+
can_rx_unregister(dev_net(dev), dev, so->txid,
SINGLE_MASK(so->txid),
isotp_rcv_echo, sk);
diff --git a/net/can/raw.c b/net/can/raw.c
index b7dbb57557f3..d1bd9cc51ebe 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -772,6 +772,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
{
struct sock *sk = sock->sk;
struct raw_sock *ro = raw_sk(sk);
+ struct sockcm_cookie sockc;
struct sk_buff *skb;
struct net_device *dev;
int ifindex;
@@ -817,11 +818,18 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (err < 0)
goto free_skb;
- skb_setup_tx_timestamp(skb, sk->sk_tsflags);
+ sockcm_init(&sockc, sk);
+ if (msg->msg_controllen) {
+ err = sock_cmsg_send(sk, msg, &sockc);
+ if (unlikely(err))
+ goto free_skb;
+ }
skb->dev = dev;
- skb->sk = sk;
skb->priority = sk->sk_priority;
+ skb->tstamp = sockc.transmit_time;
+
+ skb_setup_tx_timestamp(skb, sockc.tsflags);
err = can_send(skb, ro->loopback);
diff --git a/net/core/dev.c b/net/core/dev.c
index a601da3b4a7c..721ba9c26554 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -682,11 +682,11 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
const struct net_device *last_dev;
struct net_device_path_ctx ctx = {
.dev = dev,
- .daddr = daddr,
};
struct net_device_path *path;
int ret = 0;
+ memcpy(ctx.daddr, daddr, sizeof(ctx.daddr));
stack->num_paths = 0;
while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) {
last_dev = ctx.dev;
@@ -2998,11 +2998,12 @@ EXPORT_SYMBOL(netif_set_real_num_queues);
* @size: max skb->len of a TSO frame
*
* Set the limit on the size of TSO super-frames the device can handle.
- * Unless explicitly set the stack will assume the value of %GSO_MAX_SIZE.
+ * Unless explicitly set the stack will assume the value of
+ * %GSO_LEGACY_MAX_SIZE.
*/
void netif_set_tso_max_size(struct net_device *dev, unsigned int size)
{
- dev->tso_max_size = size;
+ dev->tso_max_size = min(GSO_MAX_SIZE, size);
if (size < READ_ONCE(dev->gso_max_size))
netif_set_gso_max_size(dev, size);
}
@@ -4329,6 +4330,7 @@ int netdev_max_backlog __read_mostly = 1000;
EXPORT_SYMBOL(netdev_max_backlog);
int netdev_tstamp_prequeue __read_mostly = 1;
+unsigned int sysctl_skb_defer_max __read_mostly = 64;
int netdev_budget __read_mostly = 300;
/* Must be at least 2 jiffes to guarantee 1 jiffy timeout */
unsigned int __read_mostly netdev_budget_usecs = 2 * USEC_PER_SEC / HZ;
@@ -4581,9 +4583,12 @@ static void rps_trigger_softirq(void *data)
#endif /* CONFIG_RPS */
/* Called from hardirq (IPI) context */
-static void trigger_rx_softirq(void *data __always_unused)
+static void trigger_rx_softirq(void *data)
{
+ struct softnet_data *sd = data;
+
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
+ smp_store_release(&sd->defer_ipi_scheduled, 0);
}
/*
@@ -6629,7 +6634,7 @@ static void skb_defer_free_flush(struct softnet_data *sd)
while (skb != NULL) {
next = skb->next;
- __kfree_skb(skb);
+ napi_consume_skb(skb, 1);
skb = next;
}
}
@@ -6650,6 +6655,8 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
for (;;) {
struct napi_struct *n;
+ skb_defer_free_flush(sd);
+
if (list_empty(&list)) {
if (!sd_has_rps_ipi_waiting(sd) && list_empty(&repoll))
goto end;
@@ -6679,8 +6686,7 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
net_rps_action_and_irq_enable(sd);
-end:
- skb_defer_free_flush(sd);
+end:;
}
struct netdev_adjacent {
@@ -10595,9 +10601,9 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
dev_net_set(dev, &init_net);
- dev->gso_max_size = GSO_MAX_SIZE;
+ dev->gso_max_size = GSO_LEGACY_MAX_SIZE;
dev->gso_max_segs = GSO_MAX_SEGS;
- dev->gro_max_size = GRO_MAX_SIZE;
+ dev->gro_max_size = GRO_LEGACY_MAX_SIZE;
dev->tso_max_size = TSO_LEGACY_MAX_SIZE;
dev->tso_max_segs = TSO_MAX_SEGS;
dev->upper_level = 1;
@@ -11381,7 +11387,7 @@ static int __init net_dev_init(void)
INIT_CSD(&sd->csd, rps_trigger_softirq, sd);
sd->cpu = i;
#endif
- INIT_CSD(&sd->defer_csd, trigger_rx_softirq, NULL);
+ INIT_CSD(&sd->defer_csd, trigger_rx_softirq, sd);
spin_lock_init(&sd->defer_lock);
init_gro_hash(&sd->backlog);
diff --git a/net/core/dev.h b/net/core/dev.h
index 328b37af90ba..cbb8a925175a 100644
--- a/net/core/dev.h
+++ b/net/core/dev.h
@@ -39,7 +39,7 @@ void dev_addr_check(struct net_device *dev);
/* sysctls not referred to from outside net/core/ */
extern int netdev_budget;
extern unsigned int netdev_budget_usecs;
-
+extern unsigned int sysctl_skb_defer_max;
extern int netdev_tstamp_prequeue;
extern int netdev_unregister_timeout_secs;
extern int weight_p;
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index b89e3e95bffc..41cac0e4834e 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -517,7 +517,7 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore,
if (!nskb)
return;
- if ((unsigned int)reason >= SKB_DROP_REASON_MAX)
+ if (unlikely(reason >= SKB_DROP_REASON_MAX || reason <= 0))
reason = SKB_DROP_REASON_NOT_SPECIFIED;
cb = NET_DM_SKB_CB(nskb);
cb->reason = reason;
diff --git a/net/core/gro.c b/net/core/gro.c
index 78110edf5d4b..b4190eb08467 100644
--- a/net/core/gro.c
+++ b/net/core/gro.c
@@ -167,6 +167,14 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
if (unlikely(p->len + len >= gro_max_size || NAPI_GRO_CB(skb)->flush))
return -E2BIG;
+ if (unlikely(p->len + len >= GRO_LEGACY_MAX_SIZE)) {
+ if (p->protocol != htons(ETH_P_IPV6) ||
+ skb_headroom(p) < sizeof(struct hop_jumbo_hdr) ||
+ ipv6_hdr(p)->nexthdr != IPPROTO_TCP ||
+ p->encapsulation)
+ return -E2BIG;
+ }
+
lp = NAPI_GRO_CB(p)->last;
pinfo = skb_shinfo(lp);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index bdc891326102..ac45328607f7 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1064,6 +1064,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
+ nla_total_size(4) /* IFLA_GSO_MAX_SEGS */
+ nla_total_size(4) /* IFLA_GSO_MAX_SIZE */
+ nla_total_size(4) /* IFLA_GRO_MAX_SIZE */
+ + nla_total_size(4) /* IFLA_TSO_MAX_SIZE */
+ + nla_total_size(4) /* IFLA_TSO_MAX_SEGS */
+ nla_total_size(1) /* IFLA_OPERSTATE */
+ nla_total_size(1) /* IFLA_LINKMODE */
+ nla_total_size(4) /* IFLA_CARRIER_CHANGES */
@@ -1769,6 +1771,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
nla_put_u32(skb, IFLA_GSO_MAX_SEGS, dev->gso_max_segs) ||
nla_put_u32(skb, IFLA_GSO_MAX_SIZE, dev->gso_max_size) ||
nla_put_u32(skb, IFLA_GRO_MAX_SIZE, dev->gro_max_size) ||
+ nla_put_u32(skb, IFLA_TSO_MAX_SIZE, dev->tso_max_size) ||
+ nla_put_u32(skb, IFLA_TSO_MAX_SEGS, dev->tso_max_segs) ||
#ifdef CONFIG_RPS
nla_put_u32(skb, IFLA_NUM_RX_QUEUES, dev->num_rx_queues) ||
#endif
@@ -1922,6 +1926,8 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_NEW_IFINDEX] = NLA_POLICY_MIN(NLA_S32, 1),
[IFLA_PARENT_DEV_NAME] = { .type = NLA_NUL_STRING },
[IFLA_GRO_MAX_SIZE] = { .type = NLA_U32 },
+ [IFLA_TSO_MAX_SIZE] = { .type = NLA_REJECT },
+ [IFLA_TSO_MAX_SEGS] = { .type = NLA_REJECT },
};
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -2354,14 +2360,6 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[],
}
}
- if (tb[IFLA_GRO_MAX_SIZE]) {
- u32 gro_max_size = nla_get_u32(tb[IFLA_GRO_MAX_SIZE]);
-
- if (gro_max_size > GRO_MAX_SIZE) {
- NL_SET_ERR_MSG(extack, "too big gro_max_size");
- return -EINVAL;
- }
- }
return 0;
}
@@ -2811,7 +2809,7 @@ static int do_setlink(const struct sk_buff *skb,
if (tb[IFLA_GSO_MAX_SIZE]) {
u32 max_size = nla_get_u32(tb[IFLA_GSO_MAX_SIZE]);
- if (max_size > GSO_MAX_SIZE || max_size > dev->tso_max_size) {
+ if (max_size > dev->tso_max_size) {
err = -EINVAL;
goto errout;
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index bd16e158b366..1d10bb4adec1 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -80,6 +80,7 @@
#include <linux/user_namespace.h>
#include <linux/indirect_call_wrapper.h>
+#include "dev.h"
#include "sock_destructor.h"
struct kmem_cache *skbuff_head_cache __ro_after_init;
@@ -771,6 +772,8 @@ void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
if (!skb_unref(skb))
return;
+ DEBUG_NET_WARN_ON_ONCE(reason <= 0 || reason >= SKB_DROP_REASON_MAX);
+
trace_kfree_skb(skb, __builtin_return_address(0), reason);
__kfree_skb(skb);
}
@@ -6494,16 +6497,21 @@ void skb_attempt_defer_free(struct sk_buff *skb)
int cpu = skb->alloc_cpu;
struct softnet_data *sd;
unsigned long flags;
+ unsigned int defer_max;
bool kick;
if (WARN_ON_ONCE(cpu >= nr_cpu_ids) ||
!cpu_online(cpu) ||
cpu == raw_smp_processor_id()) {
- __kfree_skb(skb);
+nodefer: __kfree_skb(skb);
return;
}
sd = &per_cpu(softnet_data, cpu);
+ defer_max = READ_ONCE(sysctl_skb_defer_max);
+ if (READ_ONCE(sd->defer_count) >= defer_max)
+ goto nodefer;
+
/* We do not send an IPI or any signal.
* Remote cpu will eventually call skb_defer_free_flush()
*/
@@ -6513,18 +6521,14 @@ void skb_attempt_defer_free(struct sk_buff *skb)
WRITE_ONCE(sd->defer_list, skb);
sd->defer_count++;
- /* kick every time queue length reaches 128.
- * This should avoid blocking in smp_call_function_single_async().
- * This condition should hardly be bit under normal conditions,
- * unless cpu suddenly stopped to receive NIC interrupts.
- */
- kick = sd->defer_count == 128;
+ /* Send an IPI every time queue reaches half capacity. */
+ kick = sd->defer_count == (defer_max >> 1);
spin_unlock_irqrestore(&sd->defer_lock, flags);
/* Make sure to trigger NET_RX_SOFTIRQ on the remote CPU
* if we are unlucky enough (this seems very unlikely).
*/
- if (unlikely(kick))
+ if (unlikely(kick) && !cmpxchg(&sd->defer_ipi_scheduled, 0, 1))
smp_call_function_single_async(cpu, &sd->defer_csd);
}
diff --git a/net/core/sock.c b/net/core/sock.c
index 6b287eb5427b..2ff40dd0a7a6 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -635,7 +635,9 @@ static int sock_bindtoindex_locked(struct sock *sk, int ifindex)
if (ifindex < 0)
goto out;
- sk->sk_bound_dev_if = ifindex;
+ /* Paired with all READ_ONCE() done locklessly. */
+ WRITE_ONCE(sk->sk_bound_dev_if, ifindex);
+
if (sk->sk_prot->rehash)
sk->sk_prot->rehash(sk);
sk_dst_reset(sk);
@@ -713,10 +715,11 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval,
{
int ret = -ENOPROTOOPT;
#ifdef CONFIG_NETDEVICES
+ int bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
struct net *net = sock_net(sk);
char devname[IFNAMSIZ];
- if (sk->sk_bound_dev_if == 0) {
+ if (bound_dev_if == 0) {
len = 0;
goto zero;
}
@@ -725,7 +728,7 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval,
if (len < IFNAMSIZ)
goto out;
- ret = netdev_get_name(net, devname, sk->sk_bound_dev_if);
+ ret = netdev_get_name(net, devname, bound_dev_if);
if (ret)
goto out;
@@ -1861,7 +1864,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
break;
case SO_BINDTOIFINDEX:
- v.val = sk->sk_bound_dev_if;
+ v.val = READ_ONCE(sk->sk_bound_dev_if);
break;
case SO_NETNS_COOKIE:
@@ -2293,6 +2296,19 @@ void sk_free_unlock_clone(struct sock *sk)
}
EXPORT_SYMBOL_GPL(sk_free_unlock_clone);
+static void sk_trim_gso_size(struct sock *sk)
+{
+ if (sk->sk_gso_max_size <= GSO_LEGACY_MAX_SIZE)
+ return;
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == AF_INET6 &&
+ sk_is_tcp(sk) &&
+ !ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
+ return;
+#endif
+ sk->sk_gso_max_size = GSO_LEGACY_MAX_SIZE;
+}
+
void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
u32 max_segs = 1;
@@ -2312,6 +2328,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
/* pairs with the WRITE_ONCE() in netif_set_gso_max_size() */
sk->sk_gso_max_size = READ_ONCE(dst->dev->gso_max_size);
+ sk_trim_gso_size(sk);
sk->sk_gso_max_size -= (MAX_TCP_HEADER + 1);
/* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */
max_segs = max_t(u32, READ_ONCE(dst->dev->gso_max_segs), 1);
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 195ca5c28771..ca8d38325e1e 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -578,6 +578,14 @@ static struct ctl_table net_core_table[] = {
.extra1 = SYSCTL_ONE,
.extra2 = &int_3600,
},
+ {
+ .procname = "skb_defer_max",
+ .data = &sysctl_skb_defer_max,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ },
{ }
};
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 82696ab86f74..da6e3b20cd75 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -628,7 +628,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr);
ireq->ir_mark = inet_request_mark(sk, skb);
ireq->ireq_family = AF_INET;
- ireq->ir_iif = sk->sk_bound_dev_if;
+ ireq->ir_iif = READ_ONCE(sk->sk_bound_dev_if);
/*
* Step 3: Process LISTEN state
@@ -1029,9 +1029,15 @@ static void __net_exit dccp_v4_exit_net(struct net *net)
inet_ctl_sock_destroy(pn->v4_ctl_sk);
}
+static void __net_exit dccp_v4_exit_batch(struct list_head *net_exit_list)
+{
+ inet_twsk_purge(&dccp_hashinfo, AF_INET);
+}
+
static struct pernet_operations dccp_v4_ops = {
.init = dccp_v4_init_net,
.exit = dccp_v4_exit_net,
+ .exit_batch = dccp_v4_exit_batch,
.id = &dccp_v4_pernet_id,
.size = sizeof(struct dccp_v4_pernet),
};
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 4d95b6400915..fd44638ec16b 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -374,10 +374,10 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
refcount_inc(&skb->users);
ireq->pktopts = skb;
}
- ireq->ir_iif = sk->sk_bound_dev_if;
+ ireq->ir_iif = READ_ONCE(sk->sk_bound_dev_if);
/* So that link locals have meaning */
- if (!sk->sk_bound_dev_if &&
+ if (!ireq->ir_iif &&
ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL)
ireq->ir_iif = inet6_iif(skb);
@@ -1115,9 +1115,15 @@ static void __net_exit dccp_v6_exit_net(struct net *net)
inet_ctl_sock_destroy(pn->v6_ctl_sk);
}
+static void __net_exit dccp_v6_exit_batch(struct list_head *net_exit_list)
+{
+ inet_twsk_purge(&dccp_hashinfo, AF_INET6);
+}
+
static struct pernet_operations dccp_v6_ops = {
.init = dccp_v6_init_net,
.exit = dccp_v6_exit_net,
+ .exit_batch = dccp_v6_exit_batch,
.id = &dccp_v6_pernet_id,
.size = sizeof(struct dccp_v6_pernet),
};
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index d1d78a463a06..552a53f1d5d0 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -159,7 +159,7 @@ static void dn_dst_ifdown(struct dst_entry *dst, struct net_device *dev, int how
struct neighbour *n = rt->n;
if (n && n->dev == dev) {
- n->dev = dev_net(dev)->loopback_dev;
+ n->dev = blackhole_netdev;
dev_hold(n->dev);
dev_put(dev);
}
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 1e5b53c2bb26..53f5f956d948 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -155,10 +155,14 @@ static int inet_csk_bind_conflict(const struct sock *sk,
*/
sk_for_each_bound(sk2, &tb->owners) {
- if (sk != sk2 &&
- (!sk->sk_bound_dev_if ||
- !sk2->sk_bound_dev_if ||
- sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
+ int bound_dev_if2;
+
+ 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 ||
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 5257a7575649..87354e20009a 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -373,10 +373,10 @@ begin:
sk_nulls_for_each_rcu(sk, node, &head->chain) {
if (sk->sk_hash != hash)
continue;
- if (likely(INET_MATCH(net, sk, acookie, ports, dif, sdif))) {
+ if (likely(inet_match(net, sk, acookie, ports, dif, sdif))) {
if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
goto out;
- if (unlikely(!INET_MATCH(net, sk, acookie,
+ if (unlikely(!inet_match(net, sk, acookie,
ports, dif, sdif))) {
sock_gen_put(sk);
goto begin;
@@ -426,7 +426,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
if (sk2->sk_hash != hash)
continue;
- if (likely(INET_MATCH(net, sk2, acookie, ports, dif, sdif))) {
+ if (likely(inet_match(net, sk2, acookie, ports, dif, sdif))) {
if (sk2->sk_state == TCP_TIME_WAIT) {
tw = inet_twsk(sk2);
if (twsk_unique(sk, sk2, twp))
@@ -492,14 +492,14 @@ static bool inet_ehash_lookup_by_sk(struct sock *sk,
if (esk->sk_hash != sk->sk_hash)
continue;
if (sk->sk_family == AF_INET) {
- if (unlikely(INET_MATCH(net, esk, acookie,
+ if (unlikely(inet_match(net, esk, acookie,
ports, dif, sdif))) {
return true;
}
}
#if IS_ENABLED(CONFIG_IPV6)
else if (sk->sk_family == AF_INET6) {
- if (unlikely(INET6_MATCH(esk, net,
+ if (unlikely(inet6_match(net, esk,
&sk->sk_v6_daddr,
&sk->sk_v6_rcv_saddr,
ports, dif, sdif))) {
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index 9e0bbd026560..0ec501845cb3 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -52,7 +52,8 @@ static void inet_twsk_kill(struct inet_timewait_sock *tw)
spin_unlock(lock);
/* Disassociate with bind bucket. */
- bhead = &hashinfo->bhash[tw->tw_bslot];
+ bhead = &hashinfo->bhash[inet_bhashfn(twsk_net(tw), tw->tw_num,
+ hashinfo->bhash_size)];
spin_lock(&bhead->lock);
inet_twsk_bind_unhash(tw, hashinfo);
@@ -111,12 +112,8 @@ void inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
Note, that any socket with inet->num != 0 MUST be bound in
binding cache, even if it is closed.
*/
- /* Cache inet_bhashfn(), because 'struct net' might be no longer
- * available later in inet_twsk_kill().
- */
- tw->tw_bslot = inet_bhashfn(twsk_net(tw), inet->inet_num,
- hashinfo->bhash_size);
- bhead = &hashinfo->bhash[tw->tw_bslot];
+ bhead = &hashinfo->bhash[inet_bhashfn(twsk_net(tw), inet->inet_num,
+ hashinfo->bhash_size)];
spin_lock(&bhead->lock);
tw->tw_tb = icsk->icsk_bind_hash;
WARN_ON(!icsk->icsk_bind_hash);
@@ -257,3 +254,50 @@ void __inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo, bool rearm)
}
}
EXPORT_SYMBOL_GPL(__inet_twsk_schedule);
+
+void inet_twsk_purge(struct inet_hashinfo *hashinfo, int family)
+{
+ struct inet_timewait_sock *tw;
+ struct sock *sk;
+ struct hlist_nulls_node *node;
+ unsigned int slot;
+
+ for (slot = 0; slot <= hashinfo->ehash_mask; slot++) {
+ struct inet_ehash_bucket *head = &hashinfo->ehash[slot];
+restart_rcu:
+ cond_resched();
+ rcu_read_lock();
+restart:
+ sk_nulls_for_each_rcu(sk, node, &head->chain) {
+ if (sk->sk_state != TCP_TIME_WAIT)
+ continue;
+ tw = inet_twsk(sk);
+ if ((tw->tw_family != family) ||
+ refcount_read(&twsk_net(tw)->ns.count))
+ continue;
+
+ if (unlikely(!refcount_inc_not_zero(&tw->tw_refcnt)))
+ continue;
+
+ if (unlikely((tw->tw_family != family) ||
+ refcount_read(&twsk_net(tw)->ns.count))) {
+ inet_twsk_put(tw);
+ goto restart;
+ }
+
+ rcu_read_unlock();
+ local_bh_disable();
+ inet_twsk_deschedule_put(tw);
+ local_bh_enable();
+ goto restart_rcu;
+ }
+ /* If the nulls value we got at the end of this lookup is
+ * not the expected one, we must restart lookup.
+ * We probably met an item that was moved to another chain.
+ */
+ if (get_nulls_value(node) != slot)
+ goto restart;
+ rcu_read_unlock();
+ }
+}
+EXPORT_SYMBOL_GPL(inet_twsk_purge);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 444d4a2a422d..356f535f3443 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1727,6 +1727,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
struct in_device *in_dev = __in_dev_get_rcu(dev);
unsigned int flags = RTCF_MULTICAST;
struct rtable *rth;
+ bool no_policy;
u32 itag = 0;
int err;
@@ -1737,8 +1738,12 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
if (our)
flags |= RTCF_LOCAL;
+ no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
+ if (no_policy)
+ IPCB(skb)->flags |= IPSKB_NOPOLICY;
+
rth = rt_dst_alloc(dev_net(dev)->loopback_dev, flags, RTN_MULTICAST,
- IN_DEV_ORCONF(in_dev, NOPOLICY), false);
+ no_policy, false);
if (!rth)
return -ENOBUFS;
@@ -1797,7 +1802,7 @@ static int __mkroute_input(struct sk_buff *skb,
struct rtable *rth;
int err;
struct in_device *out_dev;
- bool do_cache;
+ bool do_cache, no_policy;
u32 itag = 0;
/* get a working reference to the output device */
@@ -1842,6 +1847,10 @@ static int __mkroute_input(struct sk_buff *skb,
}
}
+ no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
+ if (no_policy)
+ IPCB(skb)->flags |= IPSKB_NOPOLICY;
+
fnhe = find_exception(nhc, daddr);
if (do_cache) {
if (fnhe)
@@ -1854,8 +1863,7 @@ static int __mkroute_input(struct sk_buff *skb,
}
}
- rth = rt_dst_alloc(out_dev->dev, 0, res->type,
- IN_DEV_ORCONF(in_dev, NOPOLICY),
+ rth = rt_dst_alloc(out_dev->dev, 0, res->type, no_policy,
IN_DEV_ORCONF(out_dev, NOXFRM));
if (!rth) {
err = -ENOBUFS;
@@ -2230,6 +2238,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
struct rtable *rth;
struct flowi4 fl4;
bool do_cache = true;
+ bool no_policy;
/* IP on this device is disabled. */
@@ -2348,6 +2357,10 @@ brd_input:
RT_CACHE_STAT_INC(in_brd);
local_input:
+ no_policy = IN_DEV_ORCONF(in_dev, NOPOLICY);
+ if (no_policy)
+ IPCB(skb)->flags |= IPSKB_NOPOLICY;
+
do_cache &= res->fi && !itag;
if (do_cache) {
struct fib_nh_common *nhc = FIB_RES_NHC(*res);
@@ -2362,7 +2375,7 @@ local_input:
rth = rt_dst_alloc(ip_rt_get_dev(net, res),
flags | RTCF_LOCAL, res->type,
- IN_DEV_ORCONF(in_dev, NOPOLICY), false);
+ no_policy, false);
if (!rth)
goto e_nobufs;
diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c
index c7d30a3bbd81..075e744bfb48 100644
--- a/net/ipv4/tcp_bbr.c
+++ b/net/ipv4/tcp_bbr.c
@@ -310,7 +310,7 @@ static u32 bbr_tso_segs_goal(struct sock *sk)
*/
bytes = min_t(unsigned long,
sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift),
- GSO_MAX_SIZE - 1 - MAX_TCP_HEADER);
+ GSO_LEGACY_MAX_SIZE - 1 - MAX_TCP_HEADER);
segs = max_t(u32, bytes / tp->mss_cache, bbr_min_tso_segs(sk));
return min(segs, 0x7FU);
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index b0918839bee7..68178e7280ce 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -372,7 +372,7 @@ static void cubictcp_state(struct sock *sk, u8 new_state)
* We apply another 100% factor because @rate is doubled at this point.
* We cap the cushion to 1ms.
*/
-static u32 hystart_ack_delay(struct sock *sk)
+static u32 hystart_ack_delay(const struct sock *sk)
{
unsigned long rate;
@@ -380,7 +380,7 @@ static u32 hystart_ack_delay(struct sock *sk)
if (!rate)
return 0;
return min_t(u64, USEC_PER_MSEC,
- div64_ul((u64)GSO_MAX_SIZE * 4 * USEC_PER_SEC, rate));
+ div64_ul((u64)sk->sk_gso_max_size * 4 * USEC_PER_SEC, rate));
}
static void hystart_update(struct sock *sk, u32 delay)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 97cfcd85f84e..3231af73e430 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2620,12 +2620,12 @@ void tcp_cwnd_reduction(struct sock *sk, int newly_acked_sacked, int newly_lost,
u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
tp->prior_cwnd - 1;
sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out;
- } else if (flag & FLAG_SND_UNA_ADVANCED && !newly_lost) {
- sndcnt = min_t(int, delta,
- max_t(int, tp->prr_delivered - tp->prr_out,
- newly_acked_sacked) + 1);
} else {
- sndcnt = min(delta, newly_acked_sacked);
+ sndcnt = max_t(int, tp->prr_delivered - tp->prr_out,
+ newly_acked_sacked);
+ if (flag & FLAG_SND_UNA_ADVANCED && !newly_lost)
+ sndcnt++;
+ sndcnt = min(delta, sndcnt);
}
/* Force a fast retransmit upon entering fast recovery */
sndcnt = max(sndcnt, (tp->prr_out ? 0 : 1));
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 218ad871c0e4..dac2650f3863 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2101,6 +2101,7 @@ bad_packet:
}
discard_it:
+ SKB_DR_OR(drop_reason, NOT_SPECIFIED);
/* Discard frame. */
kfree_skb_reason(skb, drop_reason);
return 0;
@@ -3168,6 +3169,8 @@ static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list)
{
struct net *net;
+ inet_twsk_purge(&tcp_hashinfo, AF_INET);
+
list_for_each_entry(net, net_exit_list, exit_list)
tcp_fastopen_ctx_destroy(net);
}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index b092228e4342..b4b2284ed4a2 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1553,7 +1553,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
* SO_SNDBUF values.
* Also allow first and last skb in retransmit queue to be split.
*/
- limit = sk->sk_sndbuf + 2 * SKB_TRUESIZE(GSO_MAX_SIZE);
+ limit = sk->sk_sndbuf + 2 * SKB_TRUESIZE(GSO_LEGACY_MAX_SIZE);
if (unlikely((sk->sk_wmem_queued >> 1) > limit &&
tcp_queue != TCP_FRAG_IN_WRITE_QUEUE &&
skb != tcp_rtx_queue_head(sk) &&
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 53342ce17172..aa9f2ec3dc46 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2563,7 +2563,7 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
struct sock *sk;
udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
- if (INET_MATCH(net, sk, acookie, ports, dif, sdif))
+ if (inet_match(net, sk, acookie, ports, dif, sdif))
return sk;
/* Only check first socket in chain */
break;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 39b2327edc4e..df665d4e8f0f 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -218,11 +218,11 @@ ipv4_connected:
err = -EINVAL;
goto out;
}
- sk->sk_bound_dev_if = usin->sin6_scope_id;
+ WRITE_ONCE(sk->sk_bound_dev_if, usin->sin6_scope_id);
}
if (!sk->sk_bound_dev_if && (addr_type & IPV6_ADDR_MULTICAST))
- sk->sk_bound_dev_if = np->mcast_oif;
+ WRITE_ONCE(sk->sk_bound_dev_if, np->mcast_oif);
/* Connect to link-local address requires an interface */
if (!sk->sk_bound_dev_if) {
@@ -798,7 +798,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
if (src_idx) {
if (fl6->flowi6_oif &&
src_idx != fl6->flowi6_oif &&
- (sk->sk_bound_dev_if != fl6->flowi6_oif ||
+ (READ_ONCE(sk->sk_bound_dev_if) != fl6->flowi6_oif ||
!sk_dev_equal_l3scope(sk, src_idx)))
return -EINVAL;
fl6->flowi6_oif = src_idx;
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index a758f2ab7b51..7d53d62783b1 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -71,12 +71,12 @@ begin:
sk_nulls_for_each_rcu(sk, node, &head->chain) {
if (sk->sk_hash != hash)
continue;
- if (!INET6_MATCH(sk, net, saddr, daddr, ports, dif, sdif))
+ if (!inet6_match(net, sk, saddr, daddr, ports, dif, sdif))
continue;
if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
goto out;
- if (unlikely(!INET6_MATCH(sk, net, saddr, daddr, ports, dif, sdif))) {
+ if (unlikely(!inet6_match(net, sk, saddr, daddr, ports, dif, sdif))) {
sock_gen_put(sk);
goto begin;
}
@@ -268,7 +268,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
if (sk2->sk_hash != hash)
continue;
- if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports,
+ if (likely(inet6_match(net, sk2, saddr, daddr, ports,
dif, sdif))) {
if (sk2->sk_state == TCP_TIME_WAIT) {
tw = inet_twsk(sk2);
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index c4fc03c1ac99..d12dba2dd535 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -77,7 +77,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
struct sk_buff *segs = ERR_PTR(-EINVAL);
struct ipv6hdr *ipv6h;
const struct net_offload *ops;
- int proto;
+ int proto, nexthdr;
struct frag_hdr *fptr;
unsigned int payload_len;
u8 *prevhdr;
@@ -87,6 +87,28 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
bool gso_partial;
skb_reset_network_header(skb);
+ nexthdr = ipv6_has_hopopt_jumbo(skb);
+ if (nexthdr) {
+ const int hophdr_len = sizeof(struct hop_jumbo_hdr);
+ int err;
+
+ err = skb_cow_head(skb, 0);
+ if (err < 0)
+ return ERR_PTR(err);
+
+ /* remove the HBH header.
+ * Layout: [Ethernet header][IPv6 header][HBH][TCP header]
+ */
+ memmove(skb_mac_header(skb) + hophdr_len,
+ skb_mac_header(skb),
+ ETH_HLEN + sizeof(struct ipv6hdr));
+ skb->data += hophdr_len;
+ skb->len -= hophdr_len;
+ skb->network_header += hophdr_len;
+ skb->mac_header += hophdr_len;
+ ipv6h = (struct ipv6hdr *)skb->data;
+ ipv6h->nexthdr = nexthdr;
+ }
nhoff = skb_network_header(skb) - skb_mac_header(skb);
if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
goto out;
@@ -320,15 +342,43 @@ static struct sk_buff *ip4ip6_gro_receive(struct list_head *head,
INDIRECT_CALLABLE_SCOPE int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
{
const struct net_offload *ops;
- struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + nhoff);
+ struct ipv6hdr *iph;
int err = -ENOSYS;
+ u32 payload_len;
if (skb->encapsulation) {
skb_set_inner_protocol(skb, cpu_to_be16(ETH_P_IPV6));
skb_set_inner_network_header(skb, nhoff);
}
- iph->payload_len = htons(skb->len - nhoff - sizeof(*iph));
+ payload_len = skb->len - nhoff - sizeof(*iph);
+ if (unlikely(payload_len > IPV6_MAXPLEN)) {
+ struct hop_jumbo_hdr *hop_jumbo;
+ int hoplen = sizeof(*hop_jumbo);
+
+ /* Move network header left */
+ memmove(skb_mac_header(skb) - hoplen, skb_mac_header(skb),
+ skb->transport_header - skb->mac_header);
+ skb->data -= hoplen;
+ skb->len += hoplen;
+ skb->mac_header -= hoplen;
+ skb->network_header -= hoplen;
+ iph = (struct ipv6hdr *)(skb->data + nhoff);
+ hop_jumbo = (struct hop_jumbo_hdr *)(iph + 1);
+
+ /* Build hop-by-hop options */
+ hop_jumbo->nexthdr = iph->nexthdr;
+ hop_jumbo->hdrlen = 0;
+ hop_jumbo->tlv_type = IPV6_TLV_JUMBO;
+ hop_jumbo->tlv_len = 4;
+ hop_jumbo->jumbo_payload_len = htonl(payload_len + hoplen);
+
+ iph->nexthdr = NEXTHDR_HOP;
+ iph->payload_len = 0;
+ } else {
+ iph = (struct ipv6hdr *)(skb->data + nhoff);
+ iph->payload_len = htons(payload_len);
+ }
nhoff += sizeof(*iph) + ipv6_exthdrs_len(iph, &ops);
if (WARN_ON(!ops || !ops->callbacks.gro_complete))
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index afa5bd4ad167..4081b12a01ff 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -182,7 +182,9 @@ static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff
#endif
mtu = ip6_skb_dst_mtu(skb);
- if (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu))
+ if (skb_is_gso(skb) &&
+ !(IP6CB(skb)->flags & IP6SKB_FAKEJUMBO) &&
+ !skb_gso_validate_network_len(skb, mtu))
return ip6_finish_output_gso_slowpath_drop(net, sk, skb, mtu);
if ((skb->len > mtu && !skb_is_gso(skb)) ||
@@ -252,6 +254,8 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
struct dst_entry *dst = skb_dst(skb);
struct net_device *dev = dst->dev;
struct inet6_dev *idev = ip6_dst_idev(dst);
+ struct hop_jumbo_hdr *hop_jumbo;
+ int hoplen = sizeof(*hop_jumbo);
unsigned int head_room;
struct ipv6hdr *hdr;
u8 proto = fl6->flowi6_proto;
@@ -259,7 +263,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
int hlimit = -1;
u32 mtu;
- head_room = sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dev);
+ head_room = sizeof(struct ipv6hdr) + hoplen + LL_RESERVED_SPACE(dev);
if (opt)
head_room += opt->opt_nflen + opt->opt_flen;
@@ -282,6 +286,20 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
&fl6->saddr);
}
+ if (unlikely(seg_len > IPV6_MAXPLEN)) {
+ hop_jumbo = skb_push(skb, hoplen);
+
+ hop_jumbo->nexthdr = proto;
+ hop_jumbo->hdrlen = 0;
+ hop_jumbo->tlv_type = IPV6_TLV_JUMBO;
+ hop_jumbo->tlv_len = 4;
+ hop_jumbo->jumbo_payload_len = htonl(seg_len + hoplen);
+
+ proto = IPPROTO_HOPOPTS;
+ seg_len = 0;
+ IP6CB(skb)->flags |= IP6SKB_FAKEJUMBO;
+ }
+
skb_push(skb, sizeof(struct ipv6hdr));
skb_reset_network_header(skb);
hdr = ipv6_hdr(skb);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 60bdec257ba7..28e47ca1e26d 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1509,6 +1509,7 @@ reset:
discard:
if (opt_skb)
__kfree_skb(opt_skb);
+ SKB_DR_OR(reason, NOT_SPECIFIED);
kfree_skb_reason(skb, reason);
return 0;
csum_err:
@@ -2206,9 +2207,15 @@ static void __net_exit tcpv6_net_exit(struct net *net)
inet_ctl_sock_destroy(net->ipv6.tcp_sk);
}
+static void __net_exit tcpv6_net_exit_batch(struct list_head *net_exit_list)
+{
+ inet_twsk_purge(&tcp_hashinfo, AF_INET6);
+}
+
static struct pernet_operations tcpv6_net_ops = {
.init = tcpv6_net_init,
.exit = tcpv6_net_exit,
+ .exit_batch = tcpv6_net_exit_batch,
};
int __init tcpv6_init(void)
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 3fc97d4621ac..55afd7f39c04 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -105,7 +105,7 @@ static int compute_score(struct sock *sk, struct net *net,
const struct in6_addr *daddr, unsigned short hnum,
int dif, int sdif)
{
- int score;
+ int bound_dev_if, score;
struct inet_sock *inet;
bool dev_match;
@@ -132,10 +132,11 @@ static int compute_score(struct sock *sk, struct net *net,
score++;
}
- dev_match = udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif);
+ bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
+ dev_match = udp_sk_bound_dev_eq(net, bound_dev_if, dif, sdif);
if (!dev_match)
return -1;
- if (sk->sk_bound_dev_if)
+ if (bound_dev_if)
score++;
if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
@@ -789,7 +790,7 @@ static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk,
(inet->inet_dport && inet->inet_dport != rmt_port) ||
(!ipv6_addr_any(&sk->sk_v6_daddr) &&
!ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) ||
- !udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif) ||
+ !udp_sk_bound_dev_eq(net, READ_ONCE(sk->sk_bound_dev_if), dif, sdif) ||
(!ipv6_addr_any(&sk->sk_v6_rcv_saddr) &&
!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)))
return false;
@@ -1043,7 +1044,7 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net,
udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
if (sk->sk_state == TCP_ESTABLISHED &&
- INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif, sdif))
+ inet6_match(net, sk, rmt_addr, loc_addr, ports, dif, sdif))
return sk;
/* Only check first socket in chain */
break;
@@ -1433,7 +1434,7 @@ do_udp_sendmsg:
}
if (!fl6->flowi6_oif)
- fl6->flowi6_oif = sk->sk_bound_dev_if;
+ fl6->flowi6_oif = READ_ONCE(sk->sk_bound_dev_if);
if (!fl6->flowi6_oif)
fl6->flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 175a162eec58..11e1a3a3e442 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2826,8 +2826,10 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb
void *ext_hdrs[SADB_EXT_MAX];
int err;
- pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
- BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
+ err = pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
+ BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
+ if (err)
+ return err;
memset(ext_hdrs, 0, sizeof(ext_hdrs));
err = parse_exthdrs(skb, hdr, ext_hdrs);
@@ -2898,7 +2900,7 @@ static int count_ah_combs(const struct xfrm_tmpl *t)
break;
if (!aalg->pfkey_supported)
continue;
- if (aalg_tmpl_set(t, aalg))
+ if (aalg_tmpl_set(t, aalg) && aalg->available)
sz += sizeof(struct sadb_comb);
}
return sz + sizeof(struct sadb_prop);
@@ -2916,7 +2918,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t)
if (!ealg->pfkey_supported)
continue;
- if (!(ealg_tmpl_set(t, ealg)))
+ if (!(ealg_tmpl_set(t, ealg) && ealg->available))
continue;
for (k = 1; ; k++) {
@@ -2927,7 +2929,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t)
if (!aalg->pfkey_supported)
continue;
- if (aalg_tmpl_set(t, aalg))
+ if (aalg_tmpl_set(t, aalg) && aalg->available)
sz += sizeof(struct sadb_comb);
}
}
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 6af09e188e52..4db5a554bdbd 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -50,11 +50,13 @@ static struct sock *__l2tp_ip_bind_lookup(const struct net *net, __be32 laddr,
sk_for_each_bound(sk, &l2tp_ip_bind_table) {
const struct l2tp_ip_sock *l2tp = l2tp_ip_sk(sk);
const struct inet_sock *inet = inet_sk(sk);
+ int bound_dev_if;
if (!net_eq(sock_net(sk), net))
continue;
- if (sk->sk_bound_dev_if && dif && sk->sk_bound_dev_if != dif)
+ bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
+ if (bound_dev_if && dif && bound_dev_if != dif)
continue;
if (inet->inet_rcv_saddr && laddr &&
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 217c7192691e..c6ff8bf9b55f 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -62,11 +62,13 @@ static struct sock *__l2tp_ip6_bind_lookup(const struct net *net,
const struct in6_addr *sk_laddr = inet6_rcv_saddr(sk);
const struct in6_addr *sk_raddr = &sk->sk_v6_daddr;
const struct l2tp_ip6_sock *l2tp = l2tp_ip6_sk(sk);
+ int bound_dev_if;
if (!net_eq(sock_net(sk), net))
continue;
- if (sk->sk_bound_dev_if && dif && sk->sk_bound_dev_if != dif)
+ bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
+ if (bound_dev_if && dif && bound_dev_if != dif)
continue;
if (sk_laddr && !ipv6_addr_any(sk_laddr) &&
@@ -445,7 +447,7 @@ static int l2tp_ip6_getname(struct socket *sock, struct sockaddr *uaddr,
lsa->l2tp_conn_id = lsk->conn_id;
}
if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL)
- lsa->l2tp_scope_id = sk->sk_bound_dev_if;
+ lsa->l2tp_scope_id = READ_ONCE(sk->sk_bound_dev_if);
return sizeof(*lsa);
}
@@ -560,7 +562,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
}
if (fl6.flowi6_oif == 0)
- fl6.flowi6_oif = sk->sk_bound_dev_if;
+ fl6.flowi6_oif = READ_ONCE(sk->sk_bound_dev_if);
if (msg->msg_controllen) {
opt = &opt_space;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index f1d211e61e49..f7896f257e1b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1174,7 +1174,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK);
changed |= BSS_CHANGED_HE_OBSS_PD;
- if (params->he_bss_color.enabled)
+ if (params->beacon.he_bss_color.enabled)
changed |= BSS_CHANGED_HE_BSS_COLOR;
}
@@ -1231,7 +1231,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p;
sdata->vif.bss_conf.twt_responder = params->twt_responder;
sdata->vif.bss_conf.he_obss_pd = params->he_obss_pd;
- sdata->vif.bss_conf.he_bss_color = params->he_bss_color;
+ sdata->vif.bss_conf.he_bss_color = params->beacon.he_bss_color;
sdata->vif.bss_conf.s1g = params->chandef.chan->band ==
NL80211_BAND_S1GHZ;
@@ -1316,6 +1316,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_beacon_data *params)
{
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_bss_conf *bss_conf;
struct beacon_data *old;
int err;
@@ -1335,10 +1336,28 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
err = ieee80211_assign_beacon(sdata, params, NULL, NULL);
if (err < 0)
return err;
+
+ bss_conf = &sdata->vif.bss_conf;
+ if (params->he_bss_color_valid &&
+ params->he_bss_color.enabled != bss_conf->he_bss_color.enabled) {
+ bss_conf->he_bss_color.enabled = params->he_bss_color.enabled;
+ err |= BSS_CHANGED_HE_BSS_COLOR;
+ }
+
ieee80211_bss_info_change_notify(sdata, err);
return 0;
}
+static void ieee80211_free_next_beacon(struct ieee80211_sub_if_data *sdata)
+{
+ if (!sdata->u.ap.next_beacon)
+ return;
+
+ kfree(sdata->u.ap.next_beacon->mbssid_ies);
+ kfree(sdata->u.ap.next_beacon);
+ sdata->u.ap.next_beacon = NULL;
+}
+
static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1373,11 +1392,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
mutex_unlock(&local->mtx);
- if (sdata->u.ap.next_beacon) {
- kfree(sdata->u.ap.next_beacon->mbssid_ies);
- kfree(sdata->u.ap.next_beacon);
- sdata->u.ap.next_beacon = NULL;
- }
+ ieee80211_free_next_beacon(sdata);
/* turn off carrier for this interface and dependent VLANs */
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
@@ -2928,7 +2943,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
return 0;
- ap = sdata->u.mgd.associated->bssid;
+ ap = sdata->u.mgd.bssid;
rcu_read_lock();
list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
@@ -3312,9 +3327,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
NULL, NULL);
- kfree(sdata->u.ap.next_beacon->mbssid_ies);
- kfree(sdata->u.ap.next_beacon);
- sdata->u.ap.next_beacon = NULL;
+ ieee80211_free_next_beacon(sdata);
if (err < 0)
return err;
@@ -3470,9 +3483,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
IEEE80211_MAX_CNTDWN_COUNTERS_NUM) ||
(params->n_counter_offsets_presp >
IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) {
- kfree(sdata->u.ap.next_beacon->mbssid_ies);
- kfree(sdata->u.ap.next_beacon);
- sdata->u.ap.next_beacon = NULL;
+ ieee80211_free_next_beacon(sdata);
return -EINVAL;
}
@@ -3484,9 +3495,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
err = ieee80211_assign_beacon(sdata, &params->beacon_csa, &csa, NULL);
if (err < 0) {
- kfree(sdata->u.ap.next_beacon->mbssid_ies);
- kfree(sdata->u.ap.next_beacon);
- sdata->u.ap.next_beacon = NULL;
+ ieee80211_free_next_beacon(sdata);
return err;
}
*changed |= err;
@@ -3576,11 +3585,8 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata)
{
sdata->vif.color_change_active = false;
- if (sdata->u.ap.next_beacon) {
- kfree(sdata->u.ap.next_beacon->mbssid_ies);
- kfree(sdata->u.ap.next_beacon);
- sdata->u.ap.next_beacon = NULL;
- }
+
+ ieee80211_free_next_beacon(sdata);
cfg80211_color_change_aborted_notify(sdata->dev);
}
@@ -4321,9 +4327,7 @@ ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata,
ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
NULL, NULL);
- kfree(sdata->u.ap.next_beacon->mbssid_ies);
- kfree(sdata->u.ap.next_beacon);
- sdata->u.ap.next_beacon = NULL;
+ ieee80211_free_next_beacon(sdata);
if (ret < 0)
return ret;
@@ -4366,11 +4370,7 @@ ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata,
err = ieee80211_assign_beacon(sdata, &params->beacon_color_change,
NULL, &color_change);
if (err < 0) {
- if (sdata->u.ap.next_beacon) {
- kfree(sdata->u.ap.next_beacon->mbssid_ies);
- kfree(sdata->u.ap.next_beacon);
- sdata->u.ap.next_beacon = NULL;
- }
+ ieee80211_free_next_beacon(sdata);
return err;
}
*changed |= err;
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index e490c3da3aca..cf71484658c6 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -337,7 +337,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
dev_kfree_skb(skb);
return -ENOTCONN;
}
- memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN);
+ memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr->addr3, addr, ETH_ALEN);
sdata_unlock(sdata);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d4a7ba4a8202..86ef0a46a68c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -453,9 +453,10 @@ struct ieee80211_if_managed {
bool nullfunc_failed;
u8 connection_loss:1,
driver_disconnect:1,
- reconnect:1;
+ reconnect:1,
+ associated:1;
- struct cfg80211_bss *associated;
+ struct cfg80211_bss *assoc_bss;
struct ieee80211_mgd_auth_data *auth_data;
struct ieee80211_mgd_assoc_data *assoc_data;
@@ -1148,6 +1149,9 @@ struct tpt_led_trigger {
* a scan complete for an aborted scan.
* @SCAN_HW_CANCELLED: Set for our scan work function when the scan is being
* cancelled.
+ * @SCAN_BEACON_WAIT: Set whenever we're passive scanning because of radar/no-IR
+ * and could send a probe request after receiving a beacon.
+ * @SCAN_BEACON_DONE: Beacon received, we can now send a probe request
*/
enum {
SCAN_SW_SCANNING,
@@ -1156,6 +1160,8 @@ enum {
SCAN_COMPLETED,
SCAN_ABORTED,
SCAN_HW_CANCELLED,
+ SCAN_BEACON_WAIT,
+ SCAN_BEACON_DONE,
};
/**
@@ -1854,7 +1860,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
- u8 *bssid, u8 reason, bool tx);
+ u8 reason, bool tx);
/* IBSS code */
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index a48a32f87897..5a385d4146b9 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -287,8 +287,8 @@ static void ieee80211_restart_work(struct work_struct *work)
if (sdata->vif.csa_active) {
sdata_lock(sdata);
ieee80211_sta_connection_lost(sdata,
- sdata->u.mgd.associated->bssid,
- WLAN_REASON_UNSPECIFIED, false);
+ WLAN_REASON_UNSPECIFIED,
+ false);
sdata_unlock(sdata);
}
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 07a96f7c5dc3..58d48dcae030 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1376,7 +1376,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct cfg80211_bss *cbss = ifmgd->associated;
+ struct cfg80211_bss *cbss = ifmgd->assoc_bss;
struct ieee80211_chanctx_conf *conf;
struct ieee80211_chanctx *chanctx;
enum nl80211_band current_band;
@@ -1398,7 +1398,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
bss->vht_cap_info,
ifmgd->flags,
- ifmgd->associated->bssid, &csa_ie);
+ ifmgd->bssid, &csa_ie);
if (!res) {
ch_switch.timestamp = timestamp;
@@ -1427,7 +1427,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
csa_ie.chandef.chan->band) {
sdata_info(sdata,
"AP %pM switches to different band (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
- ifmgd->associated->bssid,
+ ifmgd->bssid,
csa_ie.chandef.chan->center_freq,
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
csa_ie.chandef.center_freq2);
@@ -1440,7 +1440,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
"AP %pM switches to unsupported channel "
"(%d.%03d MHz, width:%d, CF1/2: %d.%03d/%d MHz), "
"disconnecting\n",
- ifmgd->associated->bssid,
+ ifmgd->bssid,
csa_ie.chandef.chan->center_freq,
csa_ie.chandef.chan->freq_offset,
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
@@ -1456,7 +1456,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
return;
sdata_info(sdata,
"AP %pM tries to chanswitch to same channel, ignore\n",
- ifmgd->associated->bssid);
+ ifmgd->bssid);
ifmgd->csa_ignored_same_chan = true;
return;
}
@@ -2266,7 +2266,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec(
beacon_loss_count * bss_conf->beacon_int));
- sdata->u.mgd.associated = cbss;
+ sdata->u.mgd.associated = true;
+ sdata->u.mgd.assoc_bss = cbss;
memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
ieee80211_check_rate_mask(sdata);
@@ -2361,7 +2362,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_stop_poll(sdata);
- ifmgd->associated = NULL;
+ ifmgd->associated = false;
+ ifmgd->assoc_bss = NULL;
netif_carrier_off(sdata->dev);
/*
@@ -2608,8 +2610,7 @@ static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata,
static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- const struct element *ssid;
- u8 *dst = ifmgd->associated->bssid;
+ u8 *dst = ifmgd->bssid;
u8 unicast_limit = max(1, max_probe_tries - 3);
struct sta_info *sta;
@@ -2642,19 +2643,10 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
ifmgd->nullfunc_failed = false;
ieee80211_send_nullfunc(sdata->local, sdata, false);
} else {
- int ssid_len;
-
- rcu_read_lock();
- ssid = ieee80211_bss_get_elem(ifmgd->associated, WLAN_EID_SSID);
- if (WARN_ON_ONCE(ssid == NULL))
- ssid_len = 0;
- else
- ssid_len = ssid->datalen;
-
ieee80211_mlme_send_probe_req(sdata, sdata->vif.addr, dst,
- ssid->data, ssid_len,
- ifmgd->associated->channel);
- rcu_read_unlock();
+ sdata->vif.bss_conf.ssid,
+ sdata->vif.bss_conf.ssid_len,
+ ifmgd->assoc_bss->channel);
}
ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
@@ -2744,7 +2736,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
sdata_assert_lock(sdata);
if (ifmgd->associated)
- cbss = ifmgd->associated;
+ cbss = ifmgd->assoc_bss;
else if (ifmgd->auth_data)
cbss = ifmgd->auth_data->bss;
else if (ifmgd->assoc_data)
@@ -2809,7 +2801,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
* AP is probably out of range (or not reachable for another
* reason) so remove the bss struct for that AP.
*/
- cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated);
+ cfg80211_unlink_bss(local->hw.wiphy, ifmgd->assoc_bss);
}
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
@@ -3219,8 +3211,8 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
}
if (ifmgd->associated &&
- ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) {
- const u8 *bssid = ifmgd->associated->bssid;
+ ether_addr_equal(mgmt->bssid, ifmgd->bssid)) {
+ const u8 *bssid = ifmgd->bssid;
sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n",
bssid, reason_code,
@@ -3262,7 +3254,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
return;
if (!ifmgd->associated ||
- !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
+ !ether_addr_equal(mgmt->bssid, ifmgd->bssid))
return;
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
@@ -3972,7 +3964,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status);
if (ifmgd->associated &&
- ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
+ ether_addr_equal(mgmt->bssid, ifmgd->bssid))
ieee80211_reset_ap_probe(sdata);
}
@@ -4201,9 +4193,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
if (!ifmgd->associated ||
- !ieee80211_rx_our_beacon(bssid, ifmgd->associated))
+ !ieee80211_rx_our_beacon(bssid, ifmgd->assoc_bss))
return;
- bssid = ifmgd->associated->bssid;
+ bssid = ifmgd->bssid;
if (!(rx_status->flag & RX_FLAG_NO_SIGNAL_VAL))
ieee80211_handle_beacon_sig(sdata, ifmgd, bss_conf,
@@ -4519,7 +4511,7 @@ static void ieee80211_sta_timer(struct timer_list *t)
}
void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
- u8 *bssid, u8 reason, bool tx)
+ u8 reason, bool tx)
{
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
@@ -4750,11 +4742,9 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL &&
ifmgd->associated) {
- u8 bssid[ETH_ALEN];
+ u8 *bssid = ifmgd->bssid;
int max_tries;
- memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
-
if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
max_tries = max_nullfunc_tries;
else
@@ -4774,7 +4764,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
mlme_dbg(sdata,
"No ack for nullfunc frame to AP %pM, disconnecting.\n",
bssid);
- ieee80211_sta_connection_lost(sdata, bssid,
+ ieee80211_sta_connection_lost(sdata,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
false);
}
@@ -4784,7 +4774,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
mlme_dbg(sdata,
"Failed to send nullfunc to AP %pM after %dms, disconnecting\n",
bssid, probe_wait_ms);
- ieee80211_sta_connection_lost(sdata, bssid,
+ ieee80211_sta_connection_lost(sdata,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false);
} else if (ifmgd->probe_send_count < max_tries) {
mlme_dbg(sdata,
@@ -4801,7 +4791,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
"No probe response from AP %pM after %dms, disconnecting.\n",
bssid, probe_wait_ms);
- ieee80211_sta_connection_lost(sdata, bssid,
+ ieee80211_sta_connection_lost(sdata,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false);
}
}
@@ -4934,7 +4924,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
.bssid = bssid,
};
- memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
+ memcpy(bssid, ifmgd->bssid, ETH_ALEN);
ieee80211_mgd_deauth(sdata, &req);
}
@@ -4956,7 +4946,6 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME;
mlme_dbg(sdata, "driver requested disconnect after resume\n");
ieee80211_sta_connection_lost(sdata,
- ifmgd->associated->bssid,
WLAN_REASON_UNSPECIFIED,
true);
sdata_unlock(sdata);
@@ -4967,7 +4956,6 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_HW_RESTART;
mlme_dbg(sdata, "driver requested disconnect after hardware restart\n");
ieee80211_sta_connection_lost(sdata,
- ifmgd->associated->bssid,
WLAN_REASON_UNSPECIFIED,
true);
sdata_unlock(sdata);
@@ -5842,7 +5830,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
sdata_info(sdata,
"disconnect from AP %pM for new auth to %pM\n",
- ifmgd->associated->bssid, req->bss->bssid);
+ ifmgd->bssid, req->bss->bssid);
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
WLAN_REASON_UNSPECIFIED,
false, frame_buf);
@@ -5918,7 +5906,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
sdata_info(sdata,
"disconnect from AP %pM for new assoc to %pM\n",
- ifmgd->associated->bssid, req->bss->bssid);
+ ifmgd->bssid, req->bss->bssid);
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
WLAN_REASON_UNSPECIFIED,
false, frame_buf);
@@ -6132,6 +6120,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
ifmgd->flags |= IEEE80211_STA_DISABLE_EHT;
}
+ if (req->flags & ASSOC_REQ_DISABLE_EHT)
+ ifmgd->flags |= IEEE80211_STA_DISABLE_EHT;
+
err = ieee80211_prep_connection(sdata, req->bss, true, override);
if (err)
goto err_clear;
@@ -6273,7 +6264,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
}
if (ifmgd->associated &&
- ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
+ ether_addr_equal(ifmgd->bssid, req->bssid)) {
sdata_info(sdata,
"deauthenticating from %pM by local choice (Reason: %u=%s)\n",
req->bssid, req->reason_code,
@@ -6304,7 +6295,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
* to cfg80211 while that's in a locked section already
* trying to tell us that the user wants to disconnect.
*/
- if (ifmgd->associated != req->bss)
+ if (ifmgd->assoc_bss != req->bss)
return -ENOLINK;
sdata_info(sdata,
@@ -6382,3 +6373,43 @@ void ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp)
cfg80211_cqm_beacon_loss_notify(sdata->dev, gfp);
}
EXPORT_SYMBOL(ieee80211_cqm_beacon_loss_notify);
+
+static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata,
+ int rssi_min_thold,
+ int rssi_max_thold)
+{
+ trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold);
+
+ if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+ return;
+
+ /*
+ * Scale up threshold values before storing it, as the RSSI averaging
+ * algorithm uses a scaled up value as well. Change this scaling
+ * factor if the RSSI averaging algorithm changes.
+ */
+ sdata->u.mgd.rssi_min_thold = rssi_min_thold*16;
+ sdata->u.mgd.rssi_max_thold = rssi_max_thold*16;
+}
+
+void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
+ int rssi_min_thold,
+ int rssi_max_thold)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+ WARN_ON(rssi_min_thold == rssi_max_thold ||
+ rssi_min_thold > rssi_max_thold);
+
+ _ieee80211_enable_rssi_reports(sdata, rssi_min_thold,
+ rssi_max_thold);
+}
+EXPORT_SYMBOL(ieee80211_enable_rssi_reports);
+
+void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+ _ieee80211_enable_rssi_reports(sdata, 0, 0);
+}
+EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 853c9a369d72..c5d2ab9df1e7 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -819,7 +819,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
if (!sdata->u.mgd.associated ||
(params->offchan && params->wait &&
local->ops->remain_on_channel &&
- memcmp(sdata->u.mgd.associated->bssid,
+ memcmp(sdata->u.mgd.bssid,
mgmt->bssid, ETH_ALEN)))
need_offchan = true;
sdata_unlock(sdata);
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 7b1f5c045e06..5f27e6746762 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -333,6 +333,17 @@ minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
!!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
}
+/*
+ * Look up an MCS group index based on new cfg80211 rate_info.
+ */
+static int
+minstrel_ht_ri_get_group_idx(struct rate_info *rate)
+{
+ return GROUP_IDX((rate->mcs / 8) + 1,
+ !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI),
+ !!(rate->bw & RATE_INFO_BW_40));
+}
+
static int
minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
{
@@ -342,6 +353,18 @@ minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
2*!!(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH));
}
+/*
+ * Look up an MCS group index based on new cfg80211 rate_info.
+ */
+static int
+minstrel_vht_ri_get_group_idx(struct rate_info *rate)
+{
+ return VHT_GROUP_IDX(rate->nss,
+ !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI),
+ !!(rate->bw & RATE_INFO_BW_40) +
+ 2*!!(rate->bw & RATE_INFO_BW_80));
+}
+
static struct minstrel_rate_stats *
minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
struct ieee80211_tx_rate *rate)
@@ -385,6 +408,50 @@ out:
return &mi->groups[group].rates[idx];
}
+/*
+ * Get the minstrel rate statistics for specified STA and rate info.
+ */
+static struct minstrel_rate_stats *
+minstrel_ht_ri_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ struct ieee80211_rate_status *rate_status)
+{
+ int group, idx;
+ struct rate_info *rate = &rate_status->rate_idx;
+
+ if (rate->flags & RATE_INFO_FLAGS_MCS) {
+ group = minstrel_ht_ri_get_group_idx(rate);
+ idx = rate->mcs % 8;
+ goto out;
+ }
+
+ if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) {
+ group = minstrel_vht_ri_get_group_idx(rate);
+ idx = rate->mcs;
+ goto out;
+ }
+
+ group = MINSTREL_CCK_GROUP;
+ for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) {
+ if (rate->legacy != minstrel_cck_bitrates[ mp->cck_rates[idx] ])
+ continue;
+
+ /* short preamble */
+ if ((mi->supported[group] & BIT(idx + 4)) &&
+ mi->use_short_preamble)
+ idx += 4;
+ goto out;
+ }
+
+ group = MINSTREL_OFDM_GROUP;
+ for (idx = 0; idx < ARRAY_SIZE(mp->ofdm_rates[0]); idx++)
+ if (rate->legacy == minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][idx] ])
+ goto out;
+
+ idx = 0;
+out:
+ return &mi->groups[group].rates[idx];
+}
+
static inline struct minstrel_rate_stats *
minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
{
@@ -1152,6 +1219,40 @@ minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
return false;
}
+/*
+ * Check whether rate_status contains valid information.
+ */
+static bool
+minstrel_ht_ri_txstat_valid(struct minstrel_priv *mp,
+ struct minstrel_ht_sta *mi,
+ struct ieee80211_rate_status *rate_status)
+{
+ int i;
+
+ if (!rate_status)
+ return false;
+ if (!rate_status->try_count)
+ return false;
+
+ if (rate_status->rate_idx.flags & RATE_INFO_FLAGS_MCS ||
+ rate_status->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS)
+ return true;
+
+ for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) {
+ if (rate_status->rate_idx.legacy ==
+ minstrel_cck_bitrates[ mp->cck_rates[i] ])
+ return true;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates); i++) {
+ if (rate_status->rate_idx.legacy ==
+ minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][i] ])
+ return true;
+ }
+
+ return false;
+}
+
static void
minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
{
@@ -1217,16 +1318,34 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
mi->ampdu_packets++;
mi->ampdu_len += info->status.ampdu_len;
- last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]);
- for (i = 0; !last; i++) {
- last = (i == IEEE80211_TX_MAX_RATES - 1) ||
- !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]);
+ if (st->rates && st->n_rates) {
+ last = !minstrel_ht_ri_txstat_valid(mp, mi, &(st->rates[0]));
+ for (i = 0; !last; i++) {
+ last = (i == st->n_rates - 1) ||
+ !minstrel_ht_ri_txstat_valid(mp, mi,
+ &(st->rates[i + 1]));
+
+ rate = minstrel_ht_ri_get_stats(mp, mi,
+ &(st->rates[i]));
- rate = minstrel_ht_get_stats(mp, mi, &ar[i]);
- if (last)
- rate->success += info->status.ampdu_ack_len;
+ if (last)
+ rate->success += info->status.ampdu_ack_len;
- rate->attempts += ar[i].count * info->status.ampdu_len;
+ rate->attempts += st->rates[i].try_count *
+ info->status.ampdu_len;
+ }
+ } else {
+ last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]);
+ for (i = 0; !last; i++) {
+ last = (i == IEEE80211_TX_MAX_RATES - 1) ||
+ !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]);
+
+ rate = minstrel_ht_get_stats(mp, mi, &ar[i]);
+ if (last)
+ rate->success += info->status.ampdu_ack_len;
+
+ rate->attempts += ar[i].count * info->status.ampdu_len;
+ }
}
if (mp->hw->max_rates > 1) {
@@ -1439,17 +1558,17 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
/* Start with max_tp_rate[0] */
minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[0]);
- if (mp->hw->max_rates >= 3) {
- /* At least 3 tx rates supported, use max_tp_rate[1] next */
- minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[1]);
- }
+ /* Fill up remaining, keep one entry for max_probe_rate */
+ for (; i < (mp->hw->max_rates - 1); i++)
+ minstrel_ht_set_rate(mp, mi, rates, i, mi->max_tp_rate[i]);
- if (mp->hw->max_rates >= 2) {
+ if (i < mp->hw->max_rates)
minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
- }
+
+ if (i < IEEE80211_TX_RATE_TABLE_SIZE)
+ rates->rate[i].idx = -1;
mi->sta->max_rc_amsdu_len = minstrel_ht_get_max_amsdu_len(mi);
- rates->rate[i].idx = -1;
rate_control_set_rates(mp->hw, mi->sta, rates);
}
@@ -1583,6 +1702,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
u16 ht_cap = sta->deflink.ht_cap.cap;
struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
const struct ieee80211_rate *ctl_rate;
+ struct sta_info *sta_info;
bool ldpc, erp;
int use_vht;
int n_supported = 0;
@@ -1701,6 +1821,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
n_supported++;
}
+ sta_info = container_of(sta, struct sta_info, sta);
+ mi->use_short_preamble = test_sta_flag(sta_info, WLAN_STA_SHORT_PREAMBLE) &&
+ sta_info->sdata->vif.bss_conf.use_short_preamble;
+
minstrel_ht_update_cck(mp, mi, sband, sta);
minstrel_ht_update_ofdm(mp, mi, sband, sta);
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index 06e7126727ad..1766ff0c78d3 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -180,7 +180,7 @@ struct minstrel_ht_sta {
/* tx flags to add for frames for this sta */
u32 tx_flags;
-
+ bool use_short_preamble;
u8 band;
u8 sample_seq;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 5e6b275afc9e..b698756887eb 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -281,6 +281,16 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
if (likely(!sdata1 && !sdata2))
return;
+ if (test_and_clear_bit(SCAN_BEACON_WAIT, &local->scanning)) {
+ /*
+ * we were passive scanning because of radar/no-IR, but
+ * the beacon/proberesp rx gives us an opportunity to upgrade
+ * to active scan
+ */
+ set_bit(SCAN_BEACON_DONE, &local->scanning);
+ ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
+ }
+
if (ieee80211_is_probe_resp(mgmt->frame_control)) {
struct cfg80211_scan_request *scan_req;
struct cfg80211_sched_scan_request *sched_scan_req;
@@ -787,6 +797,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
IEEE80211_CHAN_RADAR)) ||
!req->n_ssids) {
next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+ if (req->n_ssids)
+ set_bit(SCAN_BEACON_WAIT, &local->scanning);
} else {
ieee80211_scan_state_send_probe(local, &next_delay);
next_delay = IEEE80211_CHANNEL_TIME;
@@ -998,6 +1010,8 @@ set_channel:
!scan_req->n_ssids) {
*next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
local->next_scan_state = SCAN_DECISION;
+ if (scan_req->n_ssids)
+ set_bit(SCAN_BEACON_WAIT, &local->scanning);
return;
}
@@ -1090,6 +1104,8 @@ void ieee80211_scan_work(struct work_struct *work)
goto out;
}
+ clear_bit(SCAN_BEACON_WAIT, &local->scanning);
+
/*
* as long as no delay is required advance immediately
* without scheduling a new work
@@ -1100,6 +1116,10 @@ void ieee80211_scan_work(struct work_struct *work)
goto out_complete;
}
+ if (test_and_clear_bit(SCAN_BEACON_DONE, &local->scanning) &&
+ local->next_scan_state == SCAN_DECISION)
+ local->next_scan_state = SCAN_SEND_PROBE;
+
switch (local->next_scan_state) {
case SCAN_DECISION:
/* if no more bands/channels left, complete scan */
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index c563fa718d84..e69272139437 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -247,15 +247,19 @@ static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info,
struct ieee80211_tx_status *status)
{
+ struct ieee80211_rate_status *status_rate = NULL;
int len = sizeof(struct ieee80211_radiotap_header);
+ if (status && status->n_rates)
+ status_rate = &status->rates[status->n_rates - 1];
+
/* IEEE80211_RADIOTAP_RATE rate */
- if (status && status->rate && !(status->rate->flags &
- (RATE_INFO_FLAGS_MCS |
- RATE_INFO_FLAGS_DMG |
- RATE_INFO_FLAGS_EDMG |
- RATE_INFO_FLAGS_VHT_MCS |
- RATE_INFO_FLAGS_HE_MCS)))
+ if (status_rate && !(status_rate->rate_idx.flags &
+ (RATE_INFO_FLAGS_MCS |
+ RATE_INFO_FLAGS_DMG |
+ RATE_INFO_FLAGS_EDMG |
+ RATE_INFO_FLAGS_VHT_MCS |
+ RATE_INFO_FLAGS_HE_MCS)))
len += 2;
else if (info->status.rates[0].idx >= 0 &&
!(info->status.rates[0].flags &
@@ -270,12 +274,12 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info,
/* IEEE80211_RADIOTAP_MCS
* IEEE80211_RADIOTAP_VHT */
- if (status && status->rate) {
- if (status->rate->flags & RATE_INFO_FLAGS_MCS)
+ if (status_rate) {
+ if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_MCS)
len += 3;
- else if (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS)
+ else if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS)
len = ALIGN(len, 2) + 12;
- else if (status->rate->flags & RATE_INFO_FLAGS_HE_MCS)
+ else if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_HE_MCS)
len = ALIGN(len, 2) + 12;
} else if (info->status.rates[0].idx >= 0) {
if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
@@ -297,10 +301,14 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_radiotap_header *rthdr;
+ struct ieee80211_rate_status *status_rate = NULL;
unsigned char *pos;
u16 legacy_rate = 0;
u16 txflags;
+ if (status && status->n_rates)
+ status_rate = &status->rates[status->n_rates - 1];
+
rthdr = skb_push(skb, rtap_len);
memset(rthdr, 0, rtap_len);
@@ -318,13 +326,14 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
/* IEEE80211_RADIOTAP_RATE */
- if (status && status->rate) {
- if (!(status->rate->flags & (RATE_INFO_FLAGS_MCS |
- RATE_INFO_FLAGS_DMG |
- RATE_INFO_FLAGS_EDMG |
- RATE_INFO_FLAGS_VHT_MCS |
- RATE_INFO_FLAGS_HE_MCS)))
- legacy_rate = status->rate->legacy;
+ if (status_rate) {
+ if (!(status_rate->rate_idx.flags &
+ (RATE_INFO_FLAGS_MCS |
+ RATE_INFO_FLAGS_DMG |
+ RATE_INFO_FLAGS_EDMG |
+ RATE_INFO_FLAGS_VHT_MCS |
+ RATE_INFO_FLAGS_HE_MCS)))
+ legacy_rate = status_rate->rate_idx.legacy;
} else if (info->status.rates[0].idx >= 0 &&
!(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
IEEE80211_TX_RC_VHT_MCS)))
@@ -357,20 +366,21 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
*pos = retry_count;
pos++;
- if (status && status->rate &&
- (status->rate->flags & RATE_INFO_FLAGS_MCS)) {
+ if (status_rate && (status_rate->rate_idx.flags & RATE_INFO_FLAGS_MCS))
+ {
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_MCS));
pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
IEEE80211_RADIOTAP_MCS_HAVE_GI |
IEEE80211_RADIOTAP_MCS_HAVE_BW;
- if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+ if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_SHORT_GI)
pos[1] |= IEEE80211_RADIOTAP_MCS_SGI;
- if (status->rate->bw == RATE_INFO_BW_40)
+ if (status_rate->rate_idx.bw == RATE_INFO_BW_40)
pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40;
- pos[2] = status->rate->mcs;
+ pos[2] = status_rate->rate_idx.mcs;
pos += 3;
- } else if (status && status->rate &&
- (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS)) {
+ } else if (status_rate && (status_rate->rate_idx.flags &
+ RATE_INFO_FLAGS_VHT_MCS))
+ {
u16 known = local->hw.radiotap_vht_details &
(IEEE80211_RADIOTAP_VHT_KNOWN_GI |
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
@@ -385,12 +395,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
pos += 2;
/* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */
- if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+ if (status_rate->rate_idx.flags & RATE_INFO_FLAGS_SHORT_GI)
*pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
pos++;
/* u8 bandwidth */
- switch (status->rate->bw) {
+ switch (status_rate->rate_idx.bw) {
case RATE_INFO_BW_160:
*pos = 11;
break;
@@ -407,7 +417,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
pos++;
/* u8 mcs_nss[4] */
- *pos = (status->rate->mcs << 4) | status->rate->nss;
+ *pos = (status_rate->rate_idx.mcs << 4) |
+ status_rate->rate_idx.nss;
pos += 4;
/* u8 coding */
@@ -416,8 +427,9 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
pos++;
/* u16 partial_aid */
pos += 2;
- } else if (status && status->rate &&
- (status->rate->flags & RATE_INFO_FLAGS_HE_MCS)) {
+ } else if (status_rate && (status_rate->rate_idx.flags &
+ RATE_INFO_FLAGS_HE_MCS))
+ {
struct ieee80211_radiotap_he *he;
rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_HE));
@@ -435,7 +447,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
#define HE_PREP(f, val) le16_encode_bits(val, IEEE80211_RADIOTAP_HE_##f)
- he->data6 |= HE_PREP(DATA6_NSTS, status->rate->nss);
+ he->data6 |= HE_PREP(DATA6_NSTS, status_rate->rate_idx.nss);
#define CHECK_GI(s) \
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA5_GI_##s != \
@@ -445,12 +457,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
CHECK_GI(1_6);
CHECK_GI(3_2);
- he->data3 |= HE_PREP(DATA3_DATA_MCS, status->rate->mcs);
- he->data3 |= HE_PREP(DATA3_DATA_DCM, status->rate->he_dcm);
+ he->data3 |= HE_PREP(DATA3_DATA_MCS, status_rate->rate_idx.mcs);
+ he->data3 |= HE_PREP(DATA3_DATA_DCM, status_rate->rate_idx.he_dcm);
- he->data5 |= HE_PREP(DATA5_GI, status->rate->he_gi);
+ he->data5 |= HE_PREP(DATA5_GI, status_rate->rate_idx.he_gi);
- switch (status->rate->bw) {
+ switch (status_rate->rate_idx.bw) {
case RATE_INFO_BW_20:
he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC,
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ);
@@ -481,16 +493,16 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
CHECK_RU_ALLOC(2x996);
he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC,
- status->rate->he_ru_alloc + 4);
+ status_rate->rate_idx.he_ru_alloc + 4);
break;
default:
- WARN_ONCE(1, "Invalid SU BW %d\n", status->rate->bw);
+ WARN_ONCE(1, "Invalid SU BW %d\n", status_rate->rate_idx.bw);
}
pos += sizeof(struct ieee80211_radiotap_he);
}
- if ((status && status->rate) || info->status.rates[0].idx < 0)
+ if (status_rate || info->status.rates[0].idx < 0)
return;
/* IEEE80211_RADIOTAP_MCS
@@ -1111,8 +1123,9 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
if (pubsta) {
sta = container_of(pubsta, struct sta_info, sta);
- if (status->rate)
- sta->deflink.tx_stats.last_rate_info = *status->rate;
+ if (status->n_rates)
+ sta->deflink.tx_stats.last_rate_info =
+ status->rates[status->n_rates - 1].rate_idx;
}
if (skb && (tx_time_est =
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 13253eb39d09..0e4efc08c762 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3150,8 +3150,6 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
fast_tx = kmemdup(&build, sizeof(build), GFP_ATOMIC);
/* if the kmemdup fails, continue w/o fast_tx */
- if (!fast_tx)
- goto out;
out:
/* we might have raced against another call to this function */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 682a164f795a..1e26b5235add 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2854,46 +2854,6 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
return pos;
}
-static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata,
- int rssi_min_thold,
- int rssi_max_thold)
-{
- trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold);
-
- if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
- return;
-
- /*
- * Scale up threshold values before storing it, as the RSSI averaging
- * algorithm uses a scaled up value as well. Change this scaling
- * factor if the RSSI averaging algorithm changes.
- */
- sdata->u.mgd.rssi_min_thold = rssi_min_thold*16;
- sdata->u.mgd.rssi_max_thold = rssi_max_thold*16;
-}
-
-void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
- int rssi_min_thold,
- int rssi_max_thold)
-{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-
- WARN_ON(rssi_min_thold == rssi_max_thold ||
- rssi_min_thold > rssi_max_thold);
-
- _ieee80211_enable_rssi_reports(sdata, rssi_min_thold,
- rssi_max_thold);
-}
-EXPORT_SYMBOL(ieee80211_enable_rssi_reports);
-
-void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
-{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-
- _ieee80211_enable_rssi_reports(sdata, 0, 0);
-}
-EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
-
u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
u16 cap)
{
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 7ed0d268aff2..5fd8a3e8b5b4 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -311,19 +311,21 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
return RX_CONTINUE;
}
-
-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
+/*
+ * Calculate AAD for CCMP/GCMP, returning qos_tid since we
+ * need that in CCMP also for b_0.
+ */
+static u8 ccmp_gcmp_aad(struct sk_buff *skb, u8 *aad)
{
+ struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 mask_fc;
int a4_included, mgmt;
u8 qos_tid;
- u16 len_a;
- unsigned int hdrlen;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ u16 len_a = 22;
/*
* Mask FC: zero subtype b4 b5 b6 (if not mgmt)
- * Retry, PwrMgt, MoreData; set Protected
+ * Retry, PwrMgt, MoreData, Order (if Qos Data); set Protected
*/
mgmt = ieee80211_is_mgmt(hdr->frame_control);
mask_fc = hdr->frame_control;
@@ -333,30 +335,17 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
mask_fc &= ~cpu_to_le16(0x0070);
mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
- len_a = hdrlen - 2;
a4_included = ieee80211_has_a4(hdr->frame_control);
+ if (a4_included)
+ len_a += 6;
- if (ieee80211_is_data_qos(hdr->frame_control))
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
qos_tid = ieee80211_get_tid(hdr);
- else
+ mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_ORDER);
+ len_a += 2;
+ } else {
qos_tid = 0;
-
- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
- * mode authentication are not allowed to collide, yet both are derived
- * from this vector b_0. We only set L := 1 here to indicate that the
- * data size can be represented in (L+1) bytes. The CCM layer will take
- * care of storing the data length in the top (L+1) bytes and setting
- * and clearing the other bits as is required to derive the two IVs.
- */
- b_0[0] = 0x1;
-
- /* Nonce: Nonce Flags | A2 | PN
- * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
- */
- b_0[1] = qos_tid | (mgmt << 4);
- memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
- memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
+ }
/* AAD (extra authenticate-only data) / masked 802.11 header
* FC | A1 | A2 | A3 | SC | [A4] | [QC] */
@@ -376,8 +365,31 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
aad[24] = qos_tid;
}
+
+ return qos_tid;
}
+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ u8 qos_tid = ccmp_gcmp_aad(skb, aad);
+
+ /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
+ * mode authentication are not allowed to collide, yet both are derived
+ * from this vector b_0. We only set L := 1 here to indicate that the
+ * data size can be represented in (L+1) bytes. The CCM layer will take
+ * care of storing the data length in the top (L+1) bytes and setting
+ * and clearing the other bits as is required to derive the two IVs.
+ */
+ b_0[0] = 0x1;
+
+ /* Nonce: Nonce Flags | A2 | PN
+ * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
+ */
+ b_0[1] = qos_tid | (ieee80211_is_mgmt(hdr->frame_control) << 4);
+ memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
+ memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
+}
static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn, int key_id)
{
@@ -571,9 +583,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad)
{
- __le16 mask_fc;
- u8 qos_tid;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr = (void *)skb->data;
memcpy(j_0, hdr->addr2, ETH_ALEN);
memcpy(&j_0[ETH_ALEN], pn, IEEE80211_GCMP_PN_LEN);
@@ -581,40 +591,7 @@ static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad)
j_0[14] = 0;
j_0[AES_BLOCK_SIZE - 1] = 0x01;
- /* AAD (extra authenticate-only data) / masked 802.11 header
- * FC | A1 | A2 | A3 | SC | [A4] | [QC]
- */
- put_unaligned_be16(ieee80211_hdrlen(hdr->frame_control) - 2, &aad[0]);
- /* Mask FC: zero subtype b4 b5 b6 (if not mgmt)
- * Retry, PwrMgt, MoreData; set Protected
- */
- mask_fc = hdr->frame_control;
- mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY |
- IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
- if (!ieee80211_is_mgmt(hdr->frame_control))
- mask_fc &= ~cpu_to_le16(0x0070);
- mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-
- put_unaligned(mask_fc, (__le16 *)&aad[2]);
- memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
-
- /* Mask Seq#, leave Frag# */
- aad[22] = *((u8 *)&hdr->seq_ctrl) & 0x0f;
- aad[23] = 0;
-
- if (ieee80211_is_data_qos(hdr->frame_control))
- qos_tid = ieee80211_get_tid(hdr);
- else
- qos_tid = 0;
-
- if (ieee80211_has_a4(hdr->frame_control)) {
- memcpy(&aad[24], hdr->addr4, ETH_ALEN);
- aad[30] = qos_tid;
- aad[31] = 0;
- } else {
- memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
- aad[24] = qos_tid;
- }
+ ccmp_gcmp_aad(skb, aad);
}
static inline void gcmp_pn2hdr(u8 *hdr, const u8 *pn, int key_id)
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index ac3b7b8a02f6..be3b918a6d15 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -107,7 +107,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
ptr += 2;
}
if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM) {
- mp_opt->csum = (__force __sum16)get_unaligned_be16(ptr);
+ mp_opt->csum = get_unaligned((__force __sum16 *)ptr);
mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
ptr += 2;
}
@@ -221,7 +221,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
if (opsize == expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM) {
mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
- mp_opt->csum = (__force __sum16)get_unaligned_be16(ptr);
+ mp_opt->csum = get_unaligned((__force __sum16 *)ptr);
ptr += 2;
}
@@ -1282,7 +1282,7 @@ raise_win:
}
}
-u16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum)
+__sum16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum)
{
struct csum_pseudo_header header;
__wsum csum;
@@ -1298,15 +1298,25 @@ u16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum)
header.csum = 0;
csum = csum_partial(&header, sizeof(header), sum);
- return (__force u16)csum_fold(csum);
+ return csum_fold(csum);
}
-static u16 mptcp_make_csum(const struct mptcp_ext *mpext)
+static __sum16 mptcp_make_csum(const struct mptcp_ext *mpext)
{
return __mptcp_make_csum(mpext->data_seq, mpext->subflow_seq, mpext->data_len,
~csum_unfold(mpext->csum));
}
+static void put_len_csum(u16 len, __sum16 csum, void *data)
+{
+ __sum16 *sumptr = data + 2;
+ __be16 *ptr = data;
+
+ put_unaligned_be16(len, ptr);
+
+ put_unaligned(csum, sumptr);
+}
+
void mptcp_write_options(struct tcphdr *th, __be32 *ptr, struct tcp_sock *tp,
struct mptcp_out_options *opts)
{
@@ -1385,9 +1395,9 @@ void mptcp_write_options(struct tcphdr *th, __be32 *ptr, struct tcp_sock *tp,
/* data_len == 0 is reserved for the infinite mapping,
* the checksum will also be set to 0.
*/
- put_unaligned_be32(mpext->data_len << 16 |
- (mpext->data_len ? mptcp_make_csum(mpext) : 0),
- ptr);
+ put_len_csum(mpext->data_len,
+ (mpext->data_len ? mptcp_make_csum(mpext) : 0),
+ ptr);
} else {
put_unaligned_be32(mpext->data_len << 16 |
TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
@@ -1438,11 +1448,12 @@ void mptcp_write_options(struct tcphdr *th, __be32 *ptr, struct tcp_sock *tp,
goto mp_capable_done;
if (opts->csum_reqd) {
- put_unaligned_be32(opts->data_len << 16 |
- __mptcp_make_csum(opts->data_seq,
- opts->subflow_seq,
- opts->data_len,
- ~csum_unfold(opts->csum)), ptr);
+ put_len_csum(opts->data_len,
+ __mptcp_make_csum(opts->data_seq,
+ opts->subflow_seq,
+ opts->data_len,
+ ~csum_unfold(opts->csum)),
+ ptr);
} else {
put_unaligned_be32(opts->data_len << 16 |
TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index cdc2d79071f8..59a85220edc9 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -181,15 +181,14 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk, const struct sock *ssk,
struct mptcp_pm_data *pm = &msk->pm;
bool update_subflows;
- update_subflows = (ssk->sk_state == TCP_CLOSE) &&
- (subflow->request_join || subflow->mp_join) &&
+ update_subflows = (subflow->request_join || subflow->mp_join) &&
mptcp_pm_is_kernel(msk);
if (!READ_ONCE(pm->work_pending) && !update_subflows)
return;
spin_lock_bh(&pm->lock);
if (update_subflows)
- pm->subflows--;
+ __mptcp_pm_close_subflow(msk);
/* Even if this subflow is not really established, tell the PM to try
* to pick the next ones, if possible.
@@ -304,7 +303,7 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
pr_debug("fail_seq=%llu", fail_seq);
- if (mptcp_has_another_subflow(sk) || !READ_ONCE(msk->allow_infinite_fallback))
+ if (!READ_ONCE(msk->allow_infinite_fallback))
return;
if (!READ_ONCE(subflow->mp_fail_response_expect)) {
@@ -313,13 +312,10 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
subflow->send_mp_fail = 1;
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX);
subflow->send_infinite_map = 1;
- } else if (s && inet_sk_state_load(s) != TCP_CLOSE) {
+ } else if (!sock_flag(sk, SOCK_DEAD)) {
pr_debug("MP_FAIL response received");
- mptcp_data_lock(s);
- if (inet_sk_state_load(s) != TCP_CLOSE)
- sk_stop_timer(s, &s->sk_timer);
- mptcp_data_unlock(s);
+ sk_stop_timer(s, &s->sk_timer);
}
}
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 9e46cc89a8f7..17e13396024a 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1613,10 +1613,8 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
out:
/* ensure the rtx timer is running */
- mptcp_data_lock(sk);
if (!mptcp_timer_pending(sk))
mptcp_reset_timer(sk);
- mptcp_data_unlock(sk);
if (copied)
__mptcp_check_send_data_fin(sk);
}
@@ -2192,23 +2190,10 @@ mp_fail_response_expect_subflow(struct mptcp_sock *msk)
return ret;
}
-static void mptcp_check_mp_fail_response(struct mptcp_sock *msk)
-{
- struct mptcp_subflow_context *subflow;
- struct sock *sk = (struct sock *)msk;
-
- bh_lock_sock(sk);
- subflow = mp_fail_response_expect_subflow(msk);
- if (subflow)
- __set_bit(MPTCP_FAIL_NO_RESPONSE, &msk->flags);
- bh_unlock_sock(sk);
-}
-
static void mptcp_timeout_timer(struct timer_list *t)
{
struct sock *sk = from_timer(sk, t, sk_timer);
- mptcp_check_mp_fail_response(mptcp_sk(sk));
mptcp_schedule_work(sk);
sock_put(sk);
}
@@ -2529,10 +2514,8 @@ static void __mptcp_retrans(struct sock *sk)
reset_timer:
mptcp_check_and_set_pending(sk);
- mptcp_data_lock(sk);
if (!mptcp_timer_pending(sk))
mptcp_reset_timer(sk);
- mptcp_data_unlock(sk);
}
static void mptcp_mp_fail_no_response(struct mptcp_sock *msk)
@@ -2592,8 +2575,7 @@ static void mptcp_worker(struct work_struct *work)
if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
__mptcp_retrans(sk);
- if (test_and_clear_bit(MPTCP_FAIL_NO_RESPONSE, &msk->flags))
- mptcp_mp_fail_no_response(msk);
+ mptcp_mp_fail_no_response(msk);
unlock:
release_sock(sk);
@@ -2711,10 +2693,8 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
} else {
pr_debug("Sending DATA_FIN on subflow %p", ssk);
tcp_send_ack(ssk);
- mptcp_data_lock(sk);
if (!mptcp_timer_pending(sk))
mptcp_reset_timer(sk);
- mptcp_data_unlock(sk);
}
break;
}
@@ -2815,10 +2795,8 @@ static void __mptcp_destroy_sock(struct sock *sk)
/* join list will be eventually flushed (with rst) at sock lock release time*/
list_splice_init(&msk->conn_list, &conn_list);
- mptcp_data_lock(sk);
mptcp_stop_timer(sk);
sk_stop_timer(sk, &sk->sk_timer);
- mptcp_data_unlock(sk);
msk->pm.status = 0;
/* clears msk->subflow, allowing the following loop to close
@@ -2880,9 +2858,7 @@ cleanup:
__mptcp_destroy_sock(sk);
do_cancel_work = true;
} else {
- mptcp_data_lock(sk);
sk_reset_timer(sk, &sk->sk_timer, jiffies + TCP_TIMEWAIT_LEN);
- mptcp_data_unlock(sk);
}
release_sock(sk);
if (do_cancel_work)
@@ -2927,10 +2903,8 @@ static int mptcp_disconnect(struct sock *sk, int flags)
__mptcp_close_ssk(sk, ssk, subflow, MPTCP_CF_FASTCLOSE);
}
- mptcp_data_lock(sk);
mptcp_stop_timer(sk);
sk_stop_timer(sk, &sk->sk_timer);
- mptcp_data_unlock(sk);
if (mptcp_sk(sk)->token)
mptcp_event(MPTCP_EVENT_CLOSED, mptcp_sk(sk), NULL, GFP_KERNEL);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 4672901d0dfe..200f89f6d62f 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -117,7 +117,6 @@
#define MPTCP_WORK_EOF 3
#define MPTCP_FALLBACK_DONE 4
#define MPTCP_WORK_CLOSE_SUBFLOW 5
-#define MPTCP_FAIL_NO_RESPONSE 6
/* MPTCP socket release cb flags */
#define MPTCP_PUSH_PENDING 1
@@ -466,7 +465,8 @@ struct mptcp_subflow_context {
can_ack : 1, /* only after processing the remote a key */
disposable : 1, /* ctx can be free at ulp release time */
stale : 1, /* unable to snd/rcv data, do not use for xmit */
- local_id_valid : 1; /* local_id is correctly initialized */
+ local_id_valid : 1, /* local_id is correctly initialized */
+ valid_csum_seen : 1; /* at least one csum validated */
enum mptcp_data_avail data_avail;
bool mp_fail_response_expect;
u32 remote_nonce;
@@ -649,19 +649,6 @@ static inline void mptcp_subflow_tcp_fallback(struct sock *sk,
inet_csk(sk)->icsk_af_ops = ctx->icsk_af_ops;
}
-static inline bool mptcp_has_another_subflow(struct sock *ssk)
-{
- struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk), *tmp;
- struct mptcp_sock *msk = mptcp_sk(subflow->conn);
-
- mptcp_for_each_subflow(msk, tmp) {
- if (tmp != subflow)
- return true;
- }
-
- return false;
-}
-
void __init mptcp_proto_init(void);
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
int __init mptcp_proto_v6_init(void);
@@ -751,7 +738,7 @@ void mptcp_token_destroy(struct mptcp_sock *msk);
void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn);
void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg, int len, void *hmac);
-u16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum);
+__sum16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum);
void __init mptcp_pm_init(void);
void mptcp_pm_data_init(struct mptcp_sock *msk);
@@ -893,6 +880,20 @@ unsigned int mptcp_pm_get_add_addr_accept_max(const struct mptcp_sock *msk);
unsigned int mptcp_pm_get_subflows_max(const struct mptcp_sock *msk);
unsigned int mptcp_pm_get_local_addr_max(const struct mptcp_sock *msk);
+/* called under PM lock */
+static inline void __mptcp_pm_close_subflow(struct mptcp_sock *msk)
+{
+ if (--msk->pm.subflows < mptcp_pm_get_subflows_max(msk))
+ WRITE_ONCE(msk->pm.accept_subflow, true);
+}
+
+static inline void mptcp_pm_close_subflow(struct mptcp_sock *msk)
+{
+ spin_lock_bh(&msk->pm.lock);
+ __mptcp_pm_close_subflow(msk);
+ spin_unlock_bh(&msk->pm.lock);
+}
+
void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk);
void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk);
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index 826b0c1dae98..423d3826ca1e 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -756,6 +756,18 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname,
return -EOPNOTSUPP;
}
+static int mptcp_setsockopt_sol_tcp_defer(struct mptcp_sock *msk, sockptr_t optval,
+ unsigned int optlen)
+{
+ struct socket *listener;
+
+ listener = __mptcp_nmpc_socket(msk);
+ if (!listener)
+ return 0; /* TCP_DEFER_ACCEPT does not fail */
+
+ return tcp_setsockopt(listener->sk, SOL_TCP, TCP_DEFER_ACCEPT, optval, optlen);
+}
+
static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
sockptr_t optval, unsigned int optlen)
{
@@ -782,6 +794,8 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
return mptcp_setsockopt_sol_tcp_cork(msk, optval, optlen);
case TCP_NODELAY:
return mptcp_setsockopt_sol_tcp_nodelay(msk, optval, optlen);
+ case TCP_DEFER_ACCEPT:
+ return mptcp_setsockopt_sol_tcp_defer(msk, optval, optlen);
}
return -EOPNOTSUPP;
@@ -1142,6 +1156,7 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
case TCP_CONGESTION:
case TCP_INFO:
case TCP_CC_INFO:
+ case TCP_DEFER_ACCEPT:
return mptcp_getsockopt_first_sf_only(msk, SOL_TCP, optname,
optval, optlen);
case TCP_INQ:
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 6d59336a8e1e..8841e8cd9ad8 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -891,7 +891,7 @@ static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff *
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
u32 offset, seq, delta;
- u16 csum;
+ __sum16 csum;
int len;
if (!csum_reqd)
@@ -958,11 +958,14 @@ static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff *
subflow->map_data_csum);
if (unlikely(csum)) {
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DATACSUMERR);
- subflow->send_mp_fail = 1;
- MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX);
+ if (subflow->mp_join || subflow->valid_csum_seen) {
+ subflow->send_mp_fail = 1;
+ MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX);
+ }
return subflow->mp_join ? MAPPING_INVALID : MAPPING_DUMMY;
}
+ subflow->valid_csum_seen = 1;
return MAPPING_OK;
}
@@ -1013,12 +1016,9 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
pr_debug("infinite mapping received");
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX);
subflow->map_data_len = 0;
- if (sk && inet_sk_state_load(sk) != TCP_CLOSE) {
- mptcp_data_lock(sk);
- if (inet_sk_state_load(sk) != TCP_CLOSE)
- sk_stop_timer(sk, &sk->sk_timer);
- mptcp_data_unlock(sk);
- }
+ if (!sock_flag(ssk, SOCK_DEAD))
+ sk_stop_timer(sk, &sk->sk_timer);
+
return MAPPING_INVALID;
}
@@ -1153,6 +1153,18 @@ static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ss
}
}
+static bool subflow_can_fallback(struct mptcp_subflow_context *subflow)
+{
+ struct mptcp_sock *msk = mptcp_sk(subflow->conn);
+
+ if (subflow->mp_join)
+ return false;
+ else if (READ_ONCE(msk->csum_enabled))
+ return !subflow->valid_csum_seen;
+ else
+ return !subflow->fully_established;
+}
+
static bool subflow_check_data_avail(struct sock *ssk)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
@@ -1218,8 +1230,7 @@ fallback:
if (!__mptcp_check_fallback(msk)) {
/* RFC 8684 section 3.7. */
if (subflow->send_mp_fail) {
- if (mptcp_has_another_subflow(ssk) ||
- !READ_ONCE(msk->allow_infinite_fallback)) {
+ if (!READ_ONCE(msk->allow_infinite_fallback)) {
ssk->sk_err = EBADMSG;
tcp_set_state(ssk, TCP_CLOSE);
subflow->reset_transient = 0;
@@ -1227,9 +1238,8 @@ fallback:
tcp_send_active_reset(ssk, GFP_ATOMIC);
while ((skb = skb_peek(&ssk->sk_receive_queue)))
sk_eat_skb(ssk, skb);
- } else {
+ } else if (!sock_flag(ssk, SOCK_DEAD)) {
WRITE_ONCE(subflow->mp_fail_response_expect, true);
- /* The data lock is acquired in __mptcp_move_skbs() */
sk_reset_timer((struct sock *)msk,
&((struct sock *)msk)->sk_timer,
jiffies + TCP_RTO_MAX);
@@ -1238,7 +1248,7 @@ fallback:
return true;
}
- if ((subflow->mp_join || subflow->fully_established) && subflow->map_data_len) {
+ if (!subflow_can_fallback(subflow) && subflow->map_data_len) {
/* fatal protocol error, close the socket.
* subflow_error_report() will introduce the appropriate barriers
*/
@@ -1444,20 +1454,20 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
struct sockaddr_storage addr;
int remote_id = remote->id;
int local_id = loc->id;
+ int err = -ENOTCONN;
struct socket *sf;
struct sock *ssk;
u32 remote_token;
int addrlen;
int ifindex;
u8 flags;
- int err;
if (!mptcp_is_fully_established(sk))
- return -ENOTCONN;
+ goto err_out;
err = mptcp_subflow_create_socket(sk, &sf);
if (err)
- return err;
+ goto err_out;
ssk = sf->sk;
subflow = mptcp_subflow_ctx(ssk);
@@ -1515,6 +1525,12 @@ failed_unlink:
failed:
subflow->disposable = 1;
sock_release(sf);
+
+err_out:
+ /* we account subflows before the creation, and this failures will not
+ * be caught by sk_state_change()
+ */
+ mptcp_pm_close_subflow(msk);
return err;
}
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index 3db256da919b..f2def06d1070 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -179,12 +179,11 @@ EXPORT_SYMBOL_GPL(flow_offload_route_init);
static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
{
- tcp->state = TCP_CONNTRACK_ESTABLISHED;
tcp->seen[0].td_maxwin = 0;
tcp->seen[1].td_maxwin = 0;
}
-static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
+static void flow_offload_fixup_ct(struct nf_conn *ct)
{
struct net *net = nf_ct_net(ct);
int l4num = nf_ct_protonum(ct);
@@ -193,7 +192,9 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
if (l4num == IPPROTO_TCP) {
struct nf_tcp_net *tn = nf_tcp_pernet(net);
- timeout = tn->timeouts[TCP_CONNTRACK_ESTABLISHED];
+ flow_offload_fixup_tcp(&ct->proto.tcp);
+
+ timeout = tn->timeouts[ct->proto.tcp.state];
timeout -= tn->offload_timeout;
} else if (l4num == IPPROTO_UDP) {
struct nf_udp_net *tn = nf_udp_pernet(net);
@@ -211,18 +212,6 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
WRITE_ONCE(ct->timeout, nfct_time_stamp + timeout);
}
-static void flow_offload_fixup_ct_state(struct nf_conn *ct)
-{
- if (nf_ct_protonum(ct) == IPPROTO_TCP)
- flow_offload_fixup_tcp(&ct->proto.tcp);
-}
-
-static void flow_offload_fixup_ct(struct nf_conn *ct)
-{
- flow_offload_fixup_ct_state(ct);
- flow_offload_fixup_ct_timeout(ct);
-}
-
static void flow_offload_route_release(struct flow_offload *flow)
{
nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_ORIGINAL);
@@ -335,8 +324,10 @@ void flow_offload_refresh(struct nf_flowtable *flow_table,
u32 timeout;
timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
- if (READ_ONCE(flow->timeout) != timeout)
+ if (timeout - READ_ONCE(flow->timeout) > HZ)
WRITE_ONCE(flow->timeout, timeout);
+ else
+ return;
if (likely(!nf_flowtable_hw_offload(flow_table)))
return;
@@ -359,22 +350,14 @@ static void flow_offload_del(struct nf_flowtable *flow_table,
rhashtable_remove_fast(&flow_table->rhashtable,
&flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node,
nf_flow_offload_rhash_params);
-
- clear_bit(IPS_OFFLOAD_BIT, &flow->ct->status);
-
- if (nf_flow_has_expired(flow))
- flow_offload_fixup_ct(flow->ct);
- else
- flow_offload_fixup_ct_timeout(flow->ct);
-
flow_offload_free(flow);
}
void flow_offload_teardown(struct flow_offload *flow)
{
+ clear_bit(IPS_OFFLOAD_BIT, &flow->ct->status);
set_bit(NF_FLOW_TEARDOWN, &flow->flags);
-
- flow_offload_fixup_ct_state(flow->ct);
+ flow_offload_fixup_ct(flow->ct);
}
EXPORT_SYMBOL_GPL(flow_offload_teardown);
@@ -438,33 +421,12 @@ nf_flow_table_iterate(struct nf_flowtable *flow_table,
return err;
}
-static bool flow_offload_stale_dst(struct flow_offload_tuple *tuple)
-{
- struct dst_entry *dst;
-
- if (tuple->xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
- tuple->xmit_type == FLOW_OFFLOAD_XMIT_XFRM) {
- dst = tuple->dst_cache;
- if (!dst_check(dst, tuple->dst_cookie))
- return true;
- }
-
- return false;
-}
-
-static bool nf_flow_has_stale_dst(struct flow_offload *flow)
-{
- return flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple) ||
- flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple);
-}
-
static void nf_flow_offload_gc_step(struct nf_flowtable *flow_table,
struct flow_offload *flow, void *data)
{
if (nf_flow_has_expired(flow) ||
- nf_ct_is_dying(flow->ct) ||
- nf_flow_has_stale_dst(flow))
- set_bit(NF_FLOW_TEARDOWN, &flow->flags);
+ nf_ct_is_dying(flow->ct))
+ flow_offload_teardown(flow);
if (test_bit(NF_FLOW_TEARDOWN, &flow->flags)) {
if (test_bit(NF_FLOW_HW, &flow->flags)) {
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 32c0eb1b4821..b350fe9d00b0 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -248,6 +248,15 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
return true;
}
+static inline bool nf_flow_dst_check(struct flow_offload_tuple *tuple)
+{
+ if (tuple->xmit_type != FLOW_OFFLOAD_XMIT_NEIGH &&
+ tuple->xmit_type != FLOW_OFFLOAD_XMIT_XFRM)
+ return true;
+
+ return dst_check(tuple->dst_cache, tuple->dst_cookie);
+}
+
static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
const struct nf_hook_state *state,
struct dst_entry *dst)
@@ -367,6 +376,11 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
return NF_ACCEPT;
+ if (!nf_flow_dst_check(&tuplehash->tuple)) {
+ flow_offload_teardown(flow);
+ return NF_ACCEPT;
+ }
+
if (skb_try_make_writable(skb, thoff + hdrsize))
return NF_DROP;
@@ -624,6 +638,11 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff))
return NF_ACCEPT;
+ if (!nf_flow_dst_check(&tuplehash->tuple)) {
+ flow_offload_teardown(flow);
+ return NF_ACCEPT;
+ }
+
if (skb_try_make_writable(skb, thoff + hdrsize))
return NF_DROP;
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index f3ad02a399f8..12fc9cda4a2c 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -8342,16 +8342,7 @@ EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work);
static bool nft_expr_reduce(struct nft_regs_track *track,
const struct nft_expr *expr)
{
- if (!expr->ops->reduce) {
- pr_warn_once("missing reduce for expression %s ",
- expr->ops->type->name);
- return false;
- }
-
- if (nft_reduce_is_readonly(expr))
- return false;
-
- return expr->ops->reduce(track, expr);
+ return false;
}
static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *chain)
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index 50991ab1e2d2..a16cf47199b7 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -36,6 +36,15 @@ static void nft_default_forward_path(struct nf_flow_route *route,
route->tuple[dir].xmit_type = nft_xmit_type(dst_cache);
}
+static bool nft_is_valid_ether_device(const struct net_device *dev)
+{
+ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER ||
+ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr))
+ return false;
+
+ return true;
+}
+
static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
const struct dst_entry *dst_cache,
const struct nf_conn *ct,
@@ -47,6 +56,9 @@ static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
struct neighbour *n;
u8 nud_state;
+ if (!nft_is_valid_ether_device(dev))
+ goto out;
+
n = dst_neigh_lookup(dst_cache, daddr);
if (!n)
return -1;
@@ -60,6 +72,7 @@ static int nft_dev_fill_forward_path(const struct nf_flow_route *route,
if (!(nud_state & NUD_VALID))
return -1;
+out:
return dev_fill_forward_path(dev, ha, stack);
}
@@ -78,15 +91,6 @@ struct nft_forward_info {
enum flow_offload_xmit_type xmit_type;
};
-static bool nft_is_valid_ether_device(const struct net_device *dev)
-{
- if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER ||
- dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr))
- return false;
-
- return true;
-}
-
static void nft_dev_path_info(const struct net_device_path_stack *stack,
struct nft_forward_info *info,
unsigned char *ha, struct nf_flowtable *flowtable)
@@ -119,7 +123,8 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
info->indev = NULL;
break;
}
- info->outdev = path->dev;
+ if (!info->outdev)
+ info->outdev = path->dev;
info->encap[info->num_encaps].id = path->encap.id;
info->encap[info->num_encaps].proto = path->encap.proto;
info->num_encaps++;
@@ -301,7 +306,8 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
case IPPROTO_TCP:
tcph = skb_header_pointer(pkt->skb, nft_thoff(pkt),
sizeof(_tcph), &_tcph);
- if (unlikely(!tcph || tcph->fin || tcph->rst))
+ if (unlikely(!tcph || tcph->fin || tcph->rst ||
+ !nf_conntrack_tcp_established(ct)))
goto out;
break;
case IPPROTO_UDP:
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
index 6055dc9a82aa..aa5e712adf07 100644
--- a/net/nfc/nci/data.c
+++ b/net/nfc/nci/data.c
@@ -118,7 +118,7 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev,
skb_frag = nci_skb_alloc(ndev,
(NCI_DATA_HDR_SIZE + frag_len),
- GFP_KERNEL);
+ GFP_ATOMIC);
if (skb_frag == NULL) {
rc = -ENOMEM;
goto free_exit;
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 19703a649b5a..78c4b6addf15 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -153,7 +153,7 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
i = 0;
skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
- NCI_DATA_HDR_SIZE, GFP_KERNEL);
+ NCI_DATA_HDR_SIZE, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
@@ -184,7 +184,7 @@ static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
if (i < data_len) {
skb = nci_skb_alloc(ndev,
conn_info->max_pkt_payload_len +
- NCI_DATA_HDR_SIZE, GFP_KERNEL);
+ NCI_DATA_HDR_SIZE, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index d1221daa0952..823ee643371c 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -232,6 +232,10 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
for (i = 0; i < p->tcfp_nkeys; ++i) {
u32 cur = p->tcfp_keys[i].off;
+ /* sanitize the shift value for any later use */
+ p->tcfp_keys[i].shift = min_t(size_t, BITS_PER_TYPE(int) - 1,
+ p->tcfp_keys[i].shift);
+
/* The AT option can read a single byte, we can bound the actual
* value with uchar max.
*/
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 0a04468b7314..49bae3d5006b 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -311,12 +311,15 @@ META_COLLECTOR(int_sk_bound_if)
META_COLLECTOR(var_sk_bound_if)
{
+ int bound_dev_if;
+
if (skip_nonlocal(skb)) {
*err = -1;
return;
}
- if (skb->sk->sk_bound_dev_if == 0) {
+ bound_dev_if = READ_ONCE(skb->sk->sk_bound_dev_if);
+ if (bound_dev_if == 0) {
dst->value = (unsigned long) "any";
dst->len = 3;
} else {
@@ -324,7 +327,7 @@ META_COLLECTOR(var_sk_bound_if)
rcu_read_lock();
dev = dev_get_by_index_rcu(sock_net(skb->sk),
- skb->sk->sk_bound_dev_if);
+ bound_dev_if);
*err = var_dev(dev, dst);
rcu_read_unlock();
}
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 90e12bafdd48..4f43afa8678f 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -92,6 +92,7 @@ int sctp_rcv(struct sk_buff *skb)
struct sctp_chunk *chunk;
union sctp_addr src;
union sctp_addr dest;
+ int bound_dev_if;
int family;
struct sctp_af *af;
struct net *net = dev_net(skb->dev);
@@ -169,7 +170,8 @@ int sctp_rcv(struct sk_buff *skb)
* If a frame arrives on an interface and the receiving socket is
* bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
*/
- if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) {
+ bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
+ if (bound_dev_if && (bound_dev_if != af->skb_iif(skb))) {
if (transport) {
sctp_transport_put(transport);
asoc = NULL;
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 72fe6669c50d..a63df055ac57 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -134,7 +134,8 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
dst_hold(tp->dst);
sk_setup_caps(sk, tp->dst);
}
- packet->max_size = sk_can_gso(sk) ? READ_ONCE(tp->dst->dev->gso_max_size)
+ packet->max_size = sk_can_gso(sk) ? min(READ_ONCE(tp->dst->dev->gso_max_size),
+ GSO_LEGACY_MAX_SIZE)
: asoc->pathmtu;
rcu_read_unlock();
}
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index fce16b9d6e1a..5f70642a8044 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1544,9 +1544,29 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
goto out_err;
lock_sock(sk);
+ switch (sock->state) {
+ default:
+ rc = -EINVAL;
+ goto out;
+ case SS_CONNECTED:
+ rc = sk->sk_state == SMC_ACTIVE ? -EISCONN : -EINVAL;
+ goto out;
+ case SS_CONNECTING:
+ if (sk->sk_state == SMC_ACTIVE)
+ goto connected;
+ break;
+ case SS_UNCONNECTED:
+ sock->state = SS_CONNECTING;
+ break;
+ }
+
switch (sk->sk_state) {
default:
goto out;
+ case SMC_CLOSED:
+ rc = sock_error(sk) ? : -ECONNABORTED;
+ sock->state = SS_UNCONNECTED;
+ goto out;
case SMC_ACTIVE:
rc = -EISCONN;
goto out;
@@ -1565,20 +1585,24 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
goto out;
sock_hold(&smc->sk); /* sock put in passive closing */
- if (smc->use_fallback)
+ if (smc->use_fallback) {
+ sock->state = rc ? SS_CONNECTING : SS_CONNECTED;
goto out;
+ }
if (flags & O_NONBLOCK) {
if (queue_work(smc_hs_wq, &smc->connect_work))
smc->connect_nonblock = 1;
rc = -EINPROGRESS;
+ goto out;
} else {
rc = __smc_connect(smc);
if (rc < 0)
goto out;
- else
- rc = 0; /* success cases including fallback */
}
+connected:
+ rc = 0;
+ sock->state = SS_CONNECTED;
out:
release_sock(sk);
out_err:
@@ -1693,6 +1717,7 @@ struct sock *smc_accept_dequeue(struct sock *parent,
}
if (new_sock) {
sock_graft(new_sk, new_sock);
+ new_sock->state = SS_CONNECTED;
if (isk->use_fallback) {
smc_sk(new_sk)->clcsock->file = new_sock->file;
isk->clcsock->file->private_data = isk->clcsock;
@@ -2424,7 +2449,7 @@ static int smc_listen(struct socket *sock, int backlog)
rc = -EINVAL;
if ((sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) ||
- smc->connect_nonblock)
+ smc->connect_nonblock || sock->state != SS_UNCONNECTED)
goto out;
rc = 0;
@@ -2716,6 +2741,17 @@ static int smc_shutdown(struct socket *sock, int how)
lock_sock(sk);
+ if (sock->state == SS_CONNECTING) {
+ if (sk->sk_state == SMC_ACTIVE)
+ sock->state = SS_CONNECTED;
+ else if (sk->sk_state == SMC_PEERCLOSEWAIT1 ||
+ sk->sk_state == SMC_PEERCLOSEWAIT2 ||
+ sk->sk_state == SMC_APPCLOSEWAIT1 ||
+ sk->sk_state == SMC_APPCLOSEWAIT2 ||
+ sk->sk_state == SMC_APPFINCLOSEWAIT)
+ sock->state = SS_DISCONNECTING;
+ }
+
rc = -ENOTCONN;
if ((sk->sk_state != SMC_ACTIVE) &&
(sk->sk_state != SMC_PEERCLOSEWAIT1) &&
@@ -2729,6 +2765,7 @@ static int smc_shutdown(struct socket *sock, int how)
sk->sk_shutdown = smc->clcsock->sk->sk_shutdown;
if (sk->sk_shutdown == SHUTDOWN_MASK) {
sk->sk_state = SMC_CLOSED;
+ sk->sk_socket->state = SS_UNCONNECTED;
sock_put(sk);
}
goto out;
@@ -2754,6 +2791,10 @@ static int smc_shutdown(struct socket *sock, int how)
/* map sock_shutdown_cmd constants to sk_shutdown value range */
sk->sk_shutdown |= how + 1;
+ if (sk->sk_state == SMC_CLOSED)
+ sock->state = SS_UNCONNECTED;
+ else
+ sock->state = SS_DISCONNECTING;
out:
release_sock(sk);
return rc ? rc : rc1;
@@ -3139,6 +3180,7 @@ static int __smc_create(struct net *net, struct socket *sock, int protocol,
rc = -ENOBUFS;
sock->ops = &smc_sock_ops;
+ sock->state = SS_UNCONNECTED;
sk = smc_sock_alloc(net, sock, protocol);
if (!sk)
goto out;
diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c
index a3e2d3b89568..dcda4165d107 100644
--- a/net/smc/smc_ib.c
+++ b/net/smc/smc_ib.c
@@ -671,6 +671,7 @@ int smc_ib_create_queue_pair(struct smc_link *lnk)
.max_recv_wr = SMC_WR_BUF_CNT * 3,
.max_send_sge = SMC_IB_MAX_SEND_SGE,
.max_recv_sge = sges_per_buf,
+ .max_inline_data = 0,
},
.sq_sig_type = IB_SIGNAL_REQ_WR,
.qp_type = IB_QPT_RC,
diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c
index 98ca9229fe87..805a546e8c04 100644
--- a/net/smc/smc_tx.c
+++ b/net/smc/smc_tx.c
@@ -391,12 +391,20 @@ static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
int rc;
for (dstchunk = 0; dstchunk < 2; dstchunk++) {
- struct ib_sge *sge =
- wr_rdma_buf->wr_tx_rdma[dstchunk].wr.sg_list;
+ struct ib_rdma_wr *wr = &wr_rdma_buf->wr_tx_rdma[dstchunk];
+ struct ib_sge *sge = wr->wr.sg_list;
+ u64 base_addr = dma_addr;
+
+ if (dst_len < link->qp_attr.cap.max_inline_data) {
+ base_addr = (uintptr_t)conn->sndbuf_desc->cpu_addr;
+ wr->wr.send_flags |= IB_SEND_INLINE;
+ } else {
+ wr->wr.send_flags &= ~IB_SEND_INLINE;
+ }
num_sges = 0;
for (srcchunk = 0; srcchunk < 2; srcchunk++) {
- sge[srcchunk].addr = dma_addr + src_off;
+ sge[srcchunk].addr = base_addr + src_off;
sge[srcchunk].length = src_len;
num_sges++;
@@ -410,8 +418,7 @@ static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
src_len = dst_len - src_len; /* remainder */
src_len_sum += src_len;
}
- rc = smc_tx_rdma_write(conn, dst_off, num_sges,
- &wr_rdma_buf->wr_tx_rdma[dstchunk]);
+ rc = smc_tx_rdma_write(conn, dst_off, num_sges, wr);
if (rc)
return rc;
if (dst_len_sum == len)
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c
index 24be1d03fef9..26f8f240d9e8 100644
--- a/net/smc/smc_wr.c
+++ b/net/smc/smc_wr.c
@@ -554,10 +554,11 @@ void smc_wr_remember_qp_attr(struct smc_link *lnk)
static void smc_wr_init_sge(struct smc_link *lnk)
{
int sges_per_buf = (lnk->lgr->smc_version == SMC_V2) ? 2 : 1;
+ bool send_inline = (lnk->qp_attr.cap.max_inline_data > SMC_WR_TX_SIZE);
u32 i;
for (i = 0; i < lnk->wr_tx_cnt; i++) {
- lnk->wr_tx_sges[i].addr =
+ lnk->wr_tx_sges[i].addr = send_inline ? (uintptr_t)(&lnk->wr_tx_bufs[i]) :
lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE;
lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE;
lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey;
@@ -575,6 +576,8 @@ static void smc_wr_init_sge(struct smc_link *lnk)
lnk->wr_tx_ibs[i].opcode = IB_WR_SEND;
lnk->wr_tx_ibs[i].send_flags =
IB_SEND_SIGNALED | IB_SEND_SOLICITED;
+ if (send_inline)
+ lnk->wr_tx_ibs[i].send_flags |= IB_SEND_INLINE;
lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.opcode = IB_WR_RDMA_WRITE;
lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.opcode = IB_WR_RDMA_WRITE;
lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.sg_list =
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
index 8ca1d809b78d..f549e4c05def 100644
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
@@ -97,7 +97,8 @@ static int gssp_rpc_create(struct net *net, struct rpc_clnt **_clnt)
* timeout, which would result in reconnections being
* done without the correct namespace:
*/
- .flags = RPC_CLNT_CREATE_IGNORE_NULL_UNAVAIL |
+ .flags = RPC_CLNT_CREATE_NOPING |
+ RPC_CLNT_CREATE_CONNECTED |
RPC_CLNT_CREATE_NO_IDLE_TIMEOUT
};
struct rpc_clnt *clnt;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 22c28cf43eba..e2c6eca0271b 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -76,6 +76,7 @@ static int rpc_encode_header(struct rpc_task *task,
static int rpc_decode_header(struct rpc_task *task,
struct xdr_stream *xdr);
static int rpc_ping(struct rpc_clnt *clnt);
+static int rpc_ping_noreply(struct rpc_clnt *clnt);
static void rpc_check_timeout(struct rpc_task *task);
static void rpc_register_client(struct rpc_clnt *clnt)
@@ -479,9 +480,12 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
int err = rpc_ping(clnt);
- if ((args->flags & RPC_CLNT_CREATE_IGNORE_NULL_UNAVAIL) &&
- err == -EOPNOTSUPP)
- err = 0;
+ if (err != 0) {
+ rpc_shutdown_client(clnt);
+ return ERR_PTR(err);
+ }
+ } else if (args->flags & RPC_CLNT_CREATE_CONNECTED) {
+ int err = rpc_ping_noreply(clnt);
if (err != 0) {
rpc_shutdown_client(clnt);
return ERR_PTR(err);
@@ -2712,6 +2716,10 @@ static const struct rpc_procinfo rpcproc_null = {
.p_decode = rpcproc_decode_null,
};
+static const struct rpc_procinfo rpcproc_null_noreply = {
+ .p_encode = rpcproc_encode_null,
+};
+
static void
rpc_null_call_prepare(struct rpc_task *task, void *data)
{
@@ -2765,6 +2773,28 @@ static int rpc_ping(struct rpc_clnt *clnt)
return status;
}
+static int rpc_ping_noreply(struct rpc_clnt *clnt)
+{
+ struct rpc_message msg = {
+ .rpc_proc = &rpcproc_null_noreply,
+ };
+ struct rpc_task_setup task_setup_data = {
+ .rpc_client = clnt,
+ .rpc_message = &msg,
+ .callback_ops = &rpc_null_ops,
+ .flags = RPC_TASK_SOFT | RPC_TASK_SOFTCONN | RPC_TASK_NULLCREDS,
+ };
+ struct rpc_task *task;
+ int status;
+
+ task = rpc_run_task(&task_setup_data);
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+ status = task->tk_status;
+ rpc_put_task(task);
+ return status;
+}
+
struct rpc_cb_add_xprt_calldata {
struct rpc_xprt_switch *xps;
struct rpc_xprt *xprt;
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index bca00521ebc1..ec6f4b699a2b 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -411,10 +411,16 @@ static int tls_device_copy_data(void *addr, size_t bytes, struct iov_iter *i)
return 0;
}
+union tls_iter_offset {
+ struct iov_iter *msg_iter;
+ int offset;
+};
+
static int tls_push_data(struct sock *sk,
- struct iov_iter *msg_iter,
+ union tls_iter_offset iter_offset,
size_t size, int flags,
- unsigned char record_type)
+ unsigned char record_type,
+ struct page *zc_page)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_prot_info *prot = &tls_ctx->prot_info;
@@ -480,12 +486,21 @@ handle_error:
}
record = ctx->open_record;
- copy = min_t(size_t, size, (pfrag->size - pfrag->offset));
- copy = min_t(size_t, copy, (max_open_record_len - record->len));
- if (copy) {
+ copy = min_t(size_t, size, max_open_record_len - record->len);
+ if (copy && zc_page) {
+ struct page_frag zc_pfrag;
+
+ zc_pfrag.page = zc_page;
+ zc_pfrag.offset = iter_offset.offset;
+ zc_pfrag.size = copy;
+ tls_append_frag(record, &zc_pfrag, copy);
+ } else if (copy) {
+ copy = min_t(size_t, copy, pfrag->size - pfrag->offset);
+
rc = tls_device_copy_data(page_address(pfrag->page) +
- pfrag->offset, copy, msg_iter);
+ pfrag->offset, copy,
+ iter_offset.msg_iter);
if (rc)
goto handle_error;
tls_append_frag(record, pfrag, copy);
@@ -540,6 +555,7 @@ int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
{
unsigned char record_type = TLS_RECORD_TYPE_DATA;
struct tls_context *tls_ctx = tls_get_ctx(sk);
+ union tls_iter_offset iter;
int rc;
mutex_lock(&tls_ctx->tx_lock);
@@ -551,8 +567,8 @@ int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
goto out;
}
- rc = tls_push_data(sk, &msg->msg_iter, size,
- msg->msg_flags, record_type);
+ iter.msg_iter = &msg->msg_iter;
+ rc = tls_push_data(sk, iter, size, msg->msg_flags, record_type, NULL);
out:
release_sock(sk);
@@ -564,7 +580,8 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
int offset, size_t size, int flags)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
- struct iov_iter msg_iter;
+ union tls_iter_offset iter_offset;
+ struct iov_iter msg_iter;
char *kaddr;
struct kvec iov;
int rc;
@@ -580,12 +597,20 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
goto out;
}
+ if (tls_ctx->zerocopy_sendfile) {
+ iter_offset.offset = offset;
+ rc = tls_push_data(sk, iter_offset, size,
+ flags, TLS_RECORD_TYPE_DATA, page);
+ goto out;
+ }
+
kaddr = kmap(page);
iov.iov_base = kaddr + offset;
iov.iov_len = size;
iov_iter_kvec(&msg_iter, WRITE, &iov, 1, size);
- rc = tls_push_data(sk, &msg_iter, size,
- flags, TLS_RECORD_TYPE_DATA);
+ iter_offset.msg_iter = &msg_iter;
+ rc = tls_push_data(sk, iter_offset, size, flags, TLS_RECORD_TYPE_DATA,
+ NULL);
kunmap(page);
out:
@@ -656,10 +681,12 @@ EXPORT_SYMBOL(tls_get_record);
static int tls_device_push_pending_record(struct sock *sk, int flags)
{
- struct iov_iter msg_iter;
+ union tls_iter_offset iter;
+ struct iov_iter msg_iter;
iov_iter_kvec(&msg_iter, WRITE, NULL, 0, 0);
- return tls_push_data(sk, &msg_iter, 0, flags, TLS_RECORD_TYPE_DATA);
+ iter.msg_iter = &msg_iter;
+ return tls_push_data(sk, iter, 0, flags, TLS_RECORD_TYPE_DATA, NULL);
}
void tls_device_write_space(struct sock *sk, struct tls_context *ctx)
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 7b2b0e7ffee4..b91ddc110786 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -513,6 +513,26 @@ out:
return rc;
}
+static int do_tls_getsockopt_tx_zc(struct sock *sk, char __user *optval,
+ int __user *optlen)
+{
+ struct tls_context *ctx = tls_get_ctx(sk);
+ unsigned int value;
+ int len;
+
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+ if (len != sizeof(value))
+ return -EINVAL;
+
+ value = ctx->zerocopy_sendfile;
+ if (copy_to_user(optval, &value, sizeof(value)))
+ return -EFAULT;
+
+ return 0;
+}
+
static int do_tls_getsockopt(struct sock *sk, int optname,
char __user *optval, int __user *optlen)
{
@@ -524,6 +544,9 @@ static int do_tls_getsockopt(struct sock *sk, int optname,
rc = do_tls_getsockopt_conf(sk, optval, optlen,
optname == TLS_TX);
break;
+ case TLS_TX_ZEROCOPY_SENDFILE:
+ rc = do_tls_getsockopt_tx_zc(sk, optval, optlen);
+ break;
default:
rc = -ENOPROTOOPT;
break;
@@ -675,6 +698,26 @@ err_crypto_info:
return rc;
}
+static int do_tls_setsockopt_tx_zc(struct sock *sk, sockptr_t optval,
+ unsigned int optlen)
+{
+ struct tls_context *ctx = tls_get_ctx(sk);
+ unsigned int value;
+
+ if (sockptr_is_null(optval) || optlen != sizeof(value))
+ return -EINVAL;
+
+ if (copy_from_sockptr(&value, optval, sizeof(value)))
+ return -EFAULT;
+
+ if (value > 1)
+ return -EINVAL;
+
+ ctx->zerocopy_sendfile = value;
+
+ return 0;
+}
+
static int do_tls_setsockopt(struct sock *sk, int optname, sockptr_t optval,
unsigned int optlen)
{
@@ -688,6 +731,11 @@ static int do_tls_setsockopt(struct sock *sk, int optname, sockptr_t optval,
optname == TLS_TX);
release_sock(sk);
break;
+ case TLS_TX_ZEROCOPY_SENDFILE:
+ lock_sock(sk);
+ rc = do_tls_setsockopt_tx_zc(sk, optval, optlen);
+ release_sock(sk);
+ break;
default:
rc = -ENOPROTOOPT;
break;
@@ -921,6 +969,12 @@ static int tls_get_info(const struct sock *sk, struct sk_buff *skb)
if (err)
goto nla_failure;
+ if (ctx->tx_conf == TLS_HW && ctx->zerocopy_sendfile) {
+ err = nla_put_flag(skb, TLS_INFO_ZC_SENDFILE);
+ if (err)
+ goto nla_failure;
+ }
+
rcu_read_unlock();
nla_nest_end(skb, start);
return 0;
@@ -940,6 +994,7 @@ static size_t tls_get_info_size(const struct sock *sk)
nla_total_size(sizeof(u16)) + /* TLS_INFO_CIPHER */
nla_total_size(sizeof(u16)) + /* TLS_INFO_RXCONF */
nla_total_size(sizeof(u16)) + /* TLS_INFO_TXCONF */
+ nla_total_size(0) + /* TLS_INFO_ZC_SENDFILE */
0;
return size;
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 939d1673f508..0513f82b8537 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1837,15 +1837,17 @@ leave_on_list:
bool partially_consumed = chunk > len;
if (bpf_strp_enabled) {
+ /* BPF may try to queue the skb */
+ __skb_unlink(skb, &ctx->rx_list);
err = sk_psock_tls_strp_read(psock, skb);
if (err != __SK_PASS) {
rxm->offset = rxm->offset + rxm->full_len;
rxm->full_len = 0;
- __skb_unlink(skb, &ctx->rx_list);
if (err == __SK_DROP)
consume_skb(skb);
continue;
}
+ __skb_queue_tail(&ctx->rx_list, skb);
}
if (partially_consumed)
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 8b7fb4a9e07b..f74f176e0d9d 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -6,7 +6,7 @@
*
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
- * Copyright 2018-2021 Intel Corporation
+ * Copyright 2018-2022 Intel Corporation
*/
#include <linux/export.h>
@@ -1344,97 +1344,6 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
return rdev_set_monitor_channel(rdev, chandef);
}
-void
-cfg80211_get_chan_state(struct wireless_dev *wdev,
- struct ieee80211_channel **chan,
- enum cfg80211_chan_mode *chanmode,
- u8 *radar_detect)
-{
- int ret;
-
- *chan = NULL;
- *chanmode = CHAN_MODE_UNDEFINED;
-
- ASSERT_WDEV_LOCK(wdev);
-
- if (wdev->netdev && !netif_running(wdev->netdev))
- return;
-
- switch (wdev->iftype) {
- case NL80211_IFTYPE_ADHOC:
- if (wdev->current_bss) {
- *chan = wdev->current_bss->pub.channel;
- *chanmode = (wdev->ibss_fixed &&
- !wdev->ibss_dfs_possible)
- ? CHAN_MODE_SHARED
- : CHAN_MODE_EXCLUSIVE;
-
- /* consider worst-case - IBSS can try to return to the
- * original user-specified channel as creator */
- if (wdev->ibss_dfs_possible)
- *radar_detect |= BIT(wdev->chandef.width);
- return;
- }
- break;
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_P2P_CLIENT:
- if (wdev->current_bss) {
- *chan = wdev->current_bss->pub.channel;
- *chanmode = CHAN_MODE_SHARED;
- return;
- }
- break;
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_P2P_GO:
- if (wdev->cac_started) {
- *chan = wdev->chandef.chan;
- *chanmode = CHAN_MODE_SHARED;
- *radar_detect |= BIT(wdev->chandef.width);
- } else if (wdev->beacon_interval) {
- *chan = wdev->chandef.chan;
- *chanmode = CHAN_MODE_SHARED;
-
- ret = cfg80211_chandef_dfs_required(wdev->wiphy,
- &wdev->chandef,
- wdev->iftype);
- WARN_ON(ret < 0);
- if (ret > 0)
- *radar_detect |= BIT(wdev->chandef.width);
- }
- return;
- case NL80211_IFTYPE_MESH_POINT:
- if (wdev->mesh_id_len) {
- *chan = wdev->chandef.chan;
- *chanmode = CHAN_MODE_SHARED;
-
- ret = cfg80211_chandef_dfs_required(wdev->wiphy,
- &wdev->chandef,
- wdev->iftype);
- WARN_ON(ret < 0);
- if (ret > 0)
- *radar_detect |= BIT(wdev->chandef.width);
- }
- return;
- case NL80211_IFTYPE_OCB:
- if (wdev->chandef.chan) {
- *chan = wdev->chandef.chan;
- *chanmode = CHAN_MODE_SHARED;
- return;
- }
- break;
- case NL80211_IFTYPE_MONITOR:
- case NL80211_IFTYPE_AP_VLAN:
- case NL80211_IFTYPE_P2P_DEVICE:
- case NL80211_IFTYPE_NAN:
- /* these interface types don't really have a channel */
- return;
- case NL80211_IFTYPE_UNSPECIFIED:
- case NL80211_IFTYPE_WDS:
- case NUM_NL80211_IFTYPES:
- WARN_ON(1);
- }
-}
-
bool cfg80211_any_usable_channels(struct wiphy *wiphy,
unsigned long sband_mask,
u32 prohibited_flags)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3a7dbd63d8c6..5436ada91b1a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -3,7 +3,7 @@
* Wireless configuration interface internals.
*
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
*/
#ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H
@@ -281,12 +281,6 @@ struct cfg80211_cached_keys {
int def;
};
-enum cfg80211_chan_mode {
- CHAN_MODE_UNDEFINED,
- CHAN_MODE_SHARED,
- CHAN_MODE_EXCLUSIVE,
-};
-
struct cfg80211_beacon_registration {
struct list_head list;
u32 nlportid;
@@ -525,12 +519,6 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
return jiffies_to_msecs(end + (ULONG_MAX - start) + 1);
}
-void
-cfg80211_get_chan_state(struct wireless_dev *wdev,
- struct ieee80211_channel **chan,
- enum cfg80211_chan_mode *chanmode,
- u8 *radar_detect);
-
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
struct cfg80211_chan_def *chandef);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 8f98e546becf..5d89eec2869a 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -3,7 +3,7 @@
* Some IBSS support code for cfg80211.
*
* Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
- * Copyright (C) 2020-2021 Intel Corporation
+ * Copyright (C) 2020-2022 Intel Corporation
*/
#include <linux/etherdevice.h>
@@ -131,8 +131,6 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
kfree_sensitive(wdev->connect_keys);
wdev->connect_keys = connkeys;
- wdev->ibss_fixed = params->channel_fixed;
- wdev->ibss_dfs_possible = params->userspace_handles_dfs;
wdev->chandef = params->chandef;
if (connkeys) {
params->wep_keys = connkeys->params;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 02a29052e41d..740b29481bc6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -791,6 +791,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
NLA_POLICY_RANGE(NLA_BINARY,
NL80211_EHT_MIN_CAPABILITY_LEN,
NL80211_EHT_MAX_CAPABILITY_LEN),
+ [NL80211_ATTR_DISABLE_EHT] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -5181,6 +5182,30 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
return elems;
}
+static int nl80211_parse_he_bss_color(struct nlattr *attrs,
+ struct cfg80211_he_bss_color *he_bss_color)
+{
+ struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
+ int err;
+
+ err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
+ he_bss_color_policy, NULL);
+ if (err)
+ return err;
+
+ if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
+ return -EINVAL;
+
+ he_bss_color->color =
+ nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
+ he_bss_color->enabled =
+ !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
+ he_bss_color->partial =
+ nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
+
+ return 0;
+}
+
static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
struct nlattr *attrs[],
struct cfg80211_beacon_data *bcn)
@@ -5261,6 +5286,14 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
bcn->ftm_responder = -1;
}
+ if (attrs[NL80211_ATTR_HE_BSS_COLOR]) {
+ err = nl80211_parse_he_bss_color(attrs[NL80211_ATTR_HE_BSS_COLOR],
+ &bcn->he_bss_color);
+ if (err)
+ return err;
+ bcn->he_bss_color_valid = true;
+ }
+
if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
struct cfg80211_mbssid_elems *mbssid =
nl80211_parse_mbssid_elems(&rdev->wiphy,
@@ -5319,30 +5352,6 @@ static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
return 0;
}
-static int nl80211_parse_he_bss_color(struct nlattr *attrs,
- struct cfg80211_he_bss_color *he_bss_color)
-{
- struct nlattr *tb[NL80211_HE_BSS_COLOR_ATTR_MAX + 1];
- int err;
-
- err = nla_parse_nested(tb, NL80211_HE_BSS_COLOR_ATTR_MAX, attrs,
- he_bss_color_policy, NULL);
- if (err)
- return err;
-
- if (!tb[NL80211_HE_BSS_COLOR_ATTR_COLOR])
- return -EINVAL;
-
- he_bss_color->color =
- nla_get_u8(tb[NL80211_HE_BSS_COLOR_ATTR_COLOR]);
- he_bss_color->enabled =
- !nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_DISABLED]);
- he_bss_color->partial =
- nla_get_flag(tb[NL80211_HE_BSS_COLOR_ATTR_PARTIAL]);
-
- return 0;
-}
-
static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
struct nlattr *attrs,
struct cfg80211_ap_settings *params)
@@ -5734,14 +5743,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
- err = nl80211_parse_he_bss_color(
- info->attrs[NL80211_ATTR_HE_BSS_COLOR],
- &params->he_bss_color);
- if (err)
- goto out;
- }
-
if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
err = nl80211_parse_fils_discovery(rdev,
info->attrs[NL80211_ATTR_FILS_DISCOVERY],
@@ -10387,6 +10388,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
req.flags |= ASSOC_REQ_DISABLE_HE;
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
+ req.flags |= ASSOC_REQ_DISABLE_EHT;
+
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
memcpy(&req.vht_capa_mask,
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
@@ -11175,6 +11179,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HE]))
connect.flags |= ASSOC_REQ_DISABLE_HE;
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_EHT]))
+ connect.flags |= ASSOC_REQ_DISABLE_EHT;
+
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK])
memcpy(&connect.vht_capa_mask,
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]),
@@ -15301,23 +15308,79 @@ static int nl80211_set_fils_aad(struct sk_buff *skb,
#define NL80211_FLAG_CLEAR_SKB 0x20
#define NL80211_FLAG_NO_WIPHY_MTX 0x40
+#define INTERNAL_FLAG_SELECTORS(__sel) \
+ SELECTOR(__sel, NONE, 0) /* must be first */ \
+ SELECTOR(__sel, WIPHY, \
+ NL80211_FLAG_NEED_WIPHY) \
+ SELECTOR(__sel, WDEV, \
+ NL80211_FLAG_NEED_WDEV) \
+ SELECTOR(__sel, NETDEV, \
+ NL80211_FLAG_NEED_NETDEV) \
+ SELECTOR(__sel, WIPHY_RTNL, \
+ NL80211_FLAG_NEED_WIPHY | \
+ NL80211_FLAG_NEED_RTNL) \
+ SELECTOR(__sel, WIPHY_RTNL_NOMTX, \
+ NL80211_FLAG_NEED_WIPHY | \
+ NL80211_FLAG_NEED_RTNL | \
+ NL80211_FLAG_NO_WIPHY_MTX) \
+ SELECTOR(__sel, WDEV_RTNL, \
+ NL80211_FLAG_NEED_WDEV | \
+ NL80211_FLAG_NEED_RTNL) \
+ SELECTOR(__sel, NETDEV_RTNL, \
+ NL80211_FLAG_NEED_NETDEV | \
+ NL80211_FLAG_NEED_RTNL) \
+ SELECTOR(__sel, NETDEV_UP, \
+ NL80211_FLAG_NEED_NETDEV_UP) \
+ SELECTOR(__sel, NETDEV_UP_NOTMX, \
+ NL80211_FLAG_NEED_NETDEV_UP | \
+ NL80211_FLAG_NO_WIPHY_MTX) \
+ SELECTOR(__sel, NETDEV_UP_CLEAR, \
+ NL80211_FLAG_NEED_NETDEV_UP | \
+ NL80211_FLAG_CLEAR_SKB) \
+ SELECTOR(__sel, WDEV_UP, \
+ NL80211_FLAG_NEED_WDEV_UP) \
+ SELECTOR(__sel, WDEV_UP_RTNL, \
+ NL80211_FLAG_NEED_WDEV_UP | \
+ NL80211_FLAG_NEED_RTNL) \
+ SELECTOR(__sel, WIPHY_CLEAR, \
+ NL80211_FLAG_NEED_WIPHY | \
+ NL80211_FLAG_CLEAR_SKB)
+
+enum nl80211_internal_flags_selector {
+#define SELECTOR(_, name, value) NL80211_IFL_SEL_##name,
+ INTERNAL_FLAG_SELECTORS(_)
+#undef SELECTOR
+};
+
+static u32 nl80211_internal_flags[] = {
+#define SELECTOR(_, name, value) [NL80211_IFL_SEL_##name] = value,
+ INTERNAL_FLAG_SELECTORS(_)
+#undef SELECTOR
+};
+
static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev = NULL;
struct wireless_dev *wdev;
struct net_device *dev;
+ u32 internal_flags;
+
+ if (WARN_ON(ops->internal_flags >= ARRAY_SIZE(nl80211_internal_flags)))
+ return -EINVAL;
+
+ internal_flags = nl80211_internal_flags[ops->internal_flags];
rtnl_lock();
- if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
+ if (internal_flags & NL80211_FLAG_NEED_WIPHY) {
rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
if (IS_ERR(rdev)) {
rtnl_unlock();
return PTR_ERR(rdev);
}
info->user_ptr[0] = rdev;
- } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
- ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
+ } else if (internal_flags & NL80211_FLAG_NEED_NETDEV ||
+ internal_flags & NL80211_FLAG_NEED_WDEV) {
wdev = __cfg80211_wdev_from_attrs(NULL, genl_info_net(info),
info->attrs);
if (IS_ERR(wdev)) {
@@ -15328,7 +15391,7 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
dev = wdev->netdev;
rdev = wiphy_to_rdev(wdev->wiphy);
- if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
+ if (internal_flags & NL80211_FLAG_NEED_NETDEV) {
if (!dev) {
rtnl_unlock();
return -EINVAL;
@@ -15339,7 +15402,7 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
info->user_ptr[1] = wdev;
}
- if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
+ if (internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
!wdev_running(wdev)) {
rtnl_unlock();
return -ENETDOWN;
@@ -15349,12 +15412,12 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
info->user_ptr[0] = rdev;
}
- if (rdev && !(ops->internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
+ if (rdev && !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
wiphy_lock(&rdev->wiphy);
/* we keep the mutex locked until post_doit */
__release(&rdev->wiphy.mtx);
}
- if (!(ops->internal_flags & NL80211_FLAG_NEED_RTNL))
+ if (!(internal_flags & NL80211_FLAG_NEED_RTNL))
rtnl_unlock();
return 0;
@@ -15363,8 +15426,10 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
+ u32 internal_flags = nl80211_internal_flags[ops->internal_flags];
+
if (info->user_ptr[1]) {
- if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
+ if (internal_flags & NL80211_FLAG_NEED_WDEV) {
struct wireless_dev *wdev = info->user_ptr[1];
dev_put(wdev->netdev);
@@ -15374,7 +15439,7 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
}
if (info->user_ptr[0] &&
- !(ops->internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
+ !(internal_flags & NL80211_FLAG_NO_WIPHY_MTX)) {
struct cfg80211_registered_device *rdev = info->user_ptr[0];
/* we kept the mutex locked since pre_doit */
@@ -15382,7 +15447,7 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
wiphy_unlock(&rdev->wiphy);
}
- if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
+ if (internal_flags & NL80211_FLAG_NEED_RTNL)
rtnl_unlock();
/* If needed, clear the netlink message payload from the SKB
@@ -15390,7 +15455,7 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
* the heap after the SKB is freed. The netlink message header
* is still needed for further processing, so leave it intact.
*/
- if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) {
+ if (internal_flags & NL80211_FLAG_CLEAR_SKB) {
struct nlmsghdr *nlh = nlmsg_hdr(skb);
memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
@@ -15500,6 +15565,11 @@ error:
return err;
}
+#define SELECTOR(__sel, name, value) \
+ ((__sel) == (value)) ? NL80211_IFL_SEL_##name :
+int __missing_selector(void);
+#define IFLAGS(__val) INTERNAL_FLAG_SELECTORS(__val) __missing_selector()
+
static const struct genl_ops nl80211_ops[] = {
{
.cmd = NL80211_CMD_GET_WIPHY,
@@ -15508,7 +15578,7 @@ static const struct genl_ops nl80211_ops[] = {
.dumpit = nl80211_dump_wiphy,
.done = nl80211_dump_wiphy_done,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
},
};
@@ -15525,112 +15595,113 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.doit = nl80211_get_interface,
.dumpit = nl80211_dump_interface,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_WDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
},
{
.cmd = NL80211_CMD_SET_INTERFACE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_interface,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
- NL80211_FLAG_NEED_RTNL,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV |
+ NL80211_FLAG_NEED_RTNL),
},
{
.cmd = NL80211_CMD_NEW_INTERFACE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_new_interface,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WIPHY |
- NL80211_FLAG_NEED_RTNL |
- /* we take the wiphy mutex later ourselves */
- NL80211_FLAG_NO_WIPHY_MTX,
+ .internal_flags =
+ IFLAGS(NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_NEED_RTNL |
+ /* we take the wiphy mutex later ourselves */
+ NL80211_FLAG_NO_WIPHY_MTX),
},
{
.cmd = NL80211_CMD_DEL_INTERFACE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_del_interface,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV |
- NL80211_FLAG_NEED_RTNL,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
+ NL80211_FLAG_NEED_RTNL),
},
{
.cmd = NL80211_CMD_GET_KEY,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_get_key,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_SET_KEY,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_key,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_NEW_KEY,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_new_key,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_DEL_KEY,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_del_key,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_SET_BEACON,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = nl80211_set_beacon,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_START_AP,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = nl80211_start_ap,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_STOP_AP,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.flags = GENL_UNS_ADMIN_PERM,
.doit = nl80211_stop_ap,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_GET_STATION,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_get_station,
.dumpit = nl80211_dump_station,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_SET_STATION,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_station,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_NEW_STATION,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_new_station,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_DEL_STATION,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_del_station,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_GET_MPATH,
@@ -15638,7 +15709,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.doit = nl80211_get_mpath,
.dumpit = nl80211_dump_mpath,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_GET_MPP,
@@ -15646,42 +15717,41 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.doit = nl80211_get_mpp,
.dumpit = nl80211_dump_mpp,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_SET_MPATH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_mpath,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_NEW_MPATH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_new_mpath,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_DEL_MPATH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_del_mpath,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_SET_BSS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_bss,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_GET_REG,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_get_reg_do,
.dumpit = nl80211_get_reg_dump,
- .internal_flags = 0,
/* can be retrieved by unprivileged users */
},
#ifdef CONFIG_CFG80211_CRDA_SUPPORT
@@ -15690,7 +15760,6 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_reg,
.flags = GENL_ADMIN_PERM,
- .internal_flags = 0,
},
#endif
{
@@ -15710,28 +15779,28 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_get_mesh_config,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_SET_MESH_CONFIG,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_update_mesh_config,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_TRIGGER_SCAN,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_trigger_scan,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_ABORT_SCAN,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_abort_scan,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_GET_SCAN,
@@ -15743,60 +15812,58 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_start_sched_scan,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_STOP_SCHED_SCAN,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_stop_sched_scan,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_AUTHENTICATE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_authenticate,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- 0 |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_ASSOCIATE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_associate,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- 0 |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_DEAUTHENTICATE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_deauthenticate,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_DISASSOCIATE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_disassociate,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_JOIN_IBSS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_join_ibss,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_LEAVE_IBSS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_leave_ibss,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
#ifdef CONFIG_NL80211_TESTMODE
{
@@ -15805,7 +15872,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.doit = nl80211_testmode_do,
.dumpit = nl80211_testmode_dump,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
},
#endif
{
@@ -15813,34 +15880,32 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_connect,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- 0 |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_UPDATE_CONNECT_PARAMS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_update_connect_params,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- 0 |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_DISCONNECT,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_disconnect,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_SET_WIPHY_NETNS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_wiphy_netns,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WIPHY |
- NL80211_FLAG_NEED_RTNL |
- NL80211_FLAG_NO_WIPHY_MTX,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_NEED_RTNL |
+ NL80211_FLAG_NO_WIPHY_MTX),
},
{
.cmd = NL80211_CMD_GET_SURVEY,
@@ -15852,121 +15917,120 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_setdel_pmksa,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- 0 |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_DEL_PMKSA,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_setdel_pmksa,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_FLUSH_PMKSA,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_flush_pmksa,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_remain_on_channel,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_cancel_remain_on_channel,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_tx_bitrate_mask,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_REGISTER_FRAME,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_register_mgmt,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV),
},
{
.cmd = NL80211_CMD_FRAME,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_tx_mgmt,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_tx_mgmt_cancel_wait,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_SET_POWER_SAVE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_power_save,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_GET_POWER_SAVE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_get_power_save,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_SET_CQM,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_cqm,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_SET_CHANNEL,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_channel,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_JOIN_MESH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_join_mesh,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_LEAVE_MESH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_leave_mesh,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_JOIN_OCB,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_join_ocb,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_LEAVE_OCB,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_leave_ocb,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
#ifdef CONFIG_PM
{
@@ -15974,14 +16038,14 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_get_wowlan,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
},
{
.cmd = NL80211_CMD_SET_WOWLAN,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_wowlan,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
},
#endif
{
@@ -15989,126 +16053,125 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_rekey_data,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- 0 |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_TDLS_MGMT,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_tdls_mgmt,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_TDLS_OPER,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_tdls_oper,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_UNEXPECTED_FRAME,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_register_unexpected_frame,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_PROBE_CLIENT,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_probe_client,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_REGISTER_BEACONS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_register_beacons,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
},
{
.cmd = NL80211_CMD_SET_NOACK_MAP,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_noack_map,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_START_P2P_DEVICE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_start_p2p_device,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV |
- NL80211_FLAG_NEED_RTNL,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
+ NL80211_FLAG_NEED_RTNL),
},
{
.cmd = NL80211_CMD_STOP_P2P_DEVICE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_stop_p2p_device,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
- NL80211_FLAG_NEED_RTNL,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL),
},
{
.cmd = NL80211_CMD_START_NAN,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_start_nan,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV |
- NL80211_FLAG_NEED_RTNL,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV |
+ NL80211_FLAG_NEED_RTNL),
},
{
.cmd = NL80211_CMD_STOP_NAN,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_stop_nan,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
- NL80211_FLAG_NEED_RTNL,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL),
},
{
.cmd = NL80211_CMD_ADD_NAN_FUNCTION,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_nan_add_func,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_DEL_NAN_FUNCTION,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_nan_del_func,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_nan_change_config,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_SET_MCAST_RATE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_mcast_rate,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_SET_MAC_ACL,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_mac_acl,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_RADAR_DETECT,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_start_radar_detection,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- NL80211_FLAG_NO_WIPHY_MTX,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NO_WIPHY_MTX),
},
{
.cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
@@ -16120,41 +16183,41 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_update_ft_ies,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_CRIT_PROTOCOL_START,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_crit_protocol_start,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_crit_protocol_stop,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_GET_COALESCE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_get_coalesce,
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
},
{
.cmd = NL80211_CMD_SET_COALESCE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_coalesce,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
},
{
.cmd = NL80211_CMD_CHANNEL_SWITCH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_channel_switch,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_VENDOR,
@@ -16162,140 +16225,137 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.doit = nl80211_vendor_cmd,
.dumpit = nl80211_vendor_cmd_dump,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WIPHY |
- 0 |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_SET_QOS_MAP,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_qos_map,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_ADD_TX_TS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_add_tx_ts,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_DEL_TX_TS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_del_tx_ts,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_tdls_channel_switch,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_tdls_cancel_channel_switch,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_multicast_to_unicast,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_SET_PMK,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_pmk,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- 0 |
- NL80211_FLAG_CLEAR_SKB,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_CLEAR_SKB),
},
{
.cmd = NL80211_CMD_DEL_PMK,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_del_pmk,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_EXTERNAL_AUTH,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_external_auth,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_CONTROL_PORT_FRAME,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_tx_control_port,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_get_ftm_responder_stats,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_PEER_MEASUREMENT_START,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_pmsr_start,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP),
},
{
.cmd = NL80211_CMD_NOTIFY_RADAR,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_notify_radar_detection,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_UPDATE_OWE_INFO,
.doit = nl80211_update_owe_info,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_PROBE_MESH_LINK,
.doit = nl80211_probe_mesh_link,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_SET_TID_CONFIG,
.doit = nl80211_set_tid_config,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV),
},
{
.cmd = NL80211_CMD_SET_SAR_SPECS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_sar_specs,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_WIPHY |
- NL80211_FLAG_NEED_RTNL,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_NEED_RTNL),
},
{
.cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_color_change,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- NL80211_FLAG_NEED_RTNL,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{
.cmd = NL80211_CMD_SET_FILS_AAD,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_fils_aad,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
};
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index c76cd973f06e..58e83ce642ad 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -807,6 +807,8 @@ static int __init load_builtin_regdb_keys(void)
return 0;
}
+MODULE_FIRMWARE("regulatory.db.p7s");
+
static bool regdb_has_valid_signature(const u8 *data, unsigned int size)
{
const struct firmware *sig;
@@ -1078,6 +1080,8 @@ static void regdb_fw_cb(const struct firmware *fw, void *context)
release_firmware(fw);
}
+MODULE_FIRMWARE("regulatory.db");
+
static int query_regdb_file(const char *alpha2)
{
ASSERT_RTNL();
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 00bd0ecff5a1..f1876ea61fdc 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3744,7 +3744,7 @@ static int stale_bundle(struct dst_entry *dst)
void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
{
while ((dst = xfrm_dst_child(dst)) && dst->xfrm && dst->dev == dev) {
- dst->dev = dev_net(dev)->loopback_dev;
+ dst->dev = blackhole_netdev;
dev_hold(dst->dev);
dev_put(dev);
}
diff --git a/samples/trace_events/trace_custom_sched.h b/samples/trace_events/trace_custom_sched.h
index 9fdd8e7c2a45..951388334a3f 100644
--- a/samples/trace_events/trace_custom_sched.h
+++ b/samples/trace_events/trace_custom_sched.h
@@ -25,11 +25,11 @@ TRACE_CUSTOM_EVENT(sched_switch,
* that the custom event is using.
*/
TP_PROTO(bool preempt,
- unsigned int prev_state,
struct task_struct *prev,
- struct task_struct *next),
+ struct task_struct *next,
+ unsigned int prev_state),
- TP_ARGS(preempt, prev_state, prev, next),
+ TP_ARGS(preempt, prev, next, prev_state),
/*
* The next fields are where the customization happens.
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 0ae4e4e57a40..3fb8f9026e9b 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -179,7 +179,8 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
kmem_cache_free(hashtab_node_cachep, cur);
}
}
- kmem_cache_free(hashtab_node_cachep, new);
+ kfree(new->htable);
+ memset(new, 0, sizeof(*new));
return -ENOMEM;
}
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index 69cbc79fbb71..2aaaa6807174 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1094,7 +1094,8 @@ wavefront_send_sample (snd_wavefront_t *dev,
if (dataptr < data_end) {
- __get_user (sample_short, dataptr);
+ if (get_user(sample_short, dataptr))
+ return -EFAULT;
dataptr += skip;
if (data_is_unsigned) { /* GUS ? */
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index cf531c1efa13..ad292df7d805 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -937,6 +937,9 @@ static int alc_init(struct hda_codec *codec)
return 0;
}
+#define alc_free snd_hda_gen_free
+
+#ifdef CONFIG_PM
static inline void alc_shutup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -950,9 +953,6 @@ static inline void alc_shutup(struct hda_codec *codec)
alc_shutup_pins(codec);
}
-#define alc_free snd_hda_gen_free
-
-#ifdef CONFIG_PM
static void alc_power_eapd(struct hda_codec *codec)
{
alc_auto_setup_eapd(codec, false);
@@ -966,9 +966,7 @@ static int alc_suspend(struct hda_codec *codec)
spec->power_hook(codec);
return 0;
}
-#endif
-#ifdef CONFIG_PM
static int alc_resume(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -6780,6 +6778,41 @@ static void alc256_fixup_mic_no_presence_and_resume(struct hda_codec *codec,
}
}
+static void alc_fixup_dell4_mic_no_presence_quiet(struct hda_codec *codec,
+ const struct hda_fixup *fix,
+ int action)
+{
+ struct alc_spec *spec = codec->spec;
+ struct hda_input_mux *imux = &spec->gen.input_mux;
+ int i;
+
+ alc269_fixup_limit_int_mic_boost(codec, fix, action);
+
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ /**
+ * Set the vref of pin 0x19 (Headset Mic) and pin 0x1b (Headphone Mic)
+ * to Hi-Z to avoid pop noises at startup and when plugging and
+ * unplugging headphones.
+ */
+ snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
+ snd_hda_codec_set_pin_target(codec, 0x1b, PIN_VREFHIZ);
+ break;
+ case HDA_FIXUP_ACT_PROBE:
+ /**
+ * Make the internal mic (0x12) the default input source to
+ * prevent pop noises on cold boot.
+ */
+ for (i = 0; i < imux->num_items; i++) {
+ if (spec->gen.imux_pins[i] == 0x12) {
+ spec->gen.cur_mux[0] = i;
+ break;
+ }
+ }
+ break;
+ }
+}
+
enum {
ALC269_FIXUP_GPIO2,
ALC269_FIXUP_SONY_VAIO,
@@ -6821,6 +6854,7 @@ enum {
ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
+ ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET,
ALC269_FIXUP_HEADSET_MODE,
ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC,
ALC269_FIXUP_ASPIRE_HEADSET_MIC,
@@ -7012,6 +7046,7 @@ enum {
ALC245_FIXUP_CS35L41_SPI_4,
ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED,
ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED,
+ ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE,
};
static const struct hda_fixup alc269_fixups[] = {
@@ -8808,6 +8843,21 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC285_FIXUP_HP_MUTE_LED,
},
+ [ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc_fixup_dell4_mic_no_presence_quiet,
+ .chained = true,
+ .chain_id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
+ },
+ [ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x19, 0x02a1112c }, /* use as headset mic, without its own jack detect */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -8898,6 +8948,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0a2e, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
SND_PCI_QUIRK(0x1028, 0x0a30, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1028, 0x0a38, "Dell Latitude 7520", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET),
SND_PCI_QUIRK(0x1028, 0x0a58, "Dell", ALC255_FIXUP_DELL_HEADSET_MIC),
SND_PCI_QUIRK(0x1028, 0x0a61, "Dell XPS 15 9510", ALC289_FIXUP_DUAL_SPK),
SND_PCI_QUIRK(0x1028, 0x0a62, "Dell Precision 5560", ALC289_FIXUP_DUAL_SPK),
@@ -9040,6 +9091,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8995, "HP EliteBook 855 G9", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x89a4, "HP ProBook 440 G9", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x89a6, "HP ProBook 450 G9", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x89aa, "HP EliteBook 630 G9", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x89ac, "HP EliteBook 640 G9", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x89ae, "HP EliteBook 650 G9", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x89c3, "Zbook Studio G9", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
@@ -9290,6 +9342,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X),
SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS),
+ SND_PCI_QUIRK(0x1d05, 0x1096, "TongFang GMxMRxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x1100, "TongFang GKxNRxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x1111, "TongFang GMxZGxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x1119, "TongFang GMxZGxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x1129, "TongFang GMxZGxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x1147, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
@@ -9297,6 +9357,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED),
SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10),
+ SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
#if 0
/* Below is a quirk table taken from the old code.
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 0ea39565e623..40a5e3eb4ef2 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3235,6 +3235,15 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+/* Rane SL-1 */
+{
+ USB_DEVICE(0x13e5, 0x0001),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ }
+},
+
/* disabled due to regression for other devices;
* see https://bugzilla.kernel.org/show_bug.cgi?id=199905
*/
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index ab9f3da49941..fbbe59054c3f 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1822,6 +1822,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */
QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x0711, 0x5800, /* MCT Trigger 5 USB-to-HDMI */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */
diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index e1ba2d51b717..b339bf2196ca 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -348,6 +348,8 @@ enum {
IFLA_PARENT_DEV_NAME,
IFLA_PARENT_DEV_BUS_NAME,
IFLA_GRO_MAX_SIZE,
+ IFLA_TSO_MAX_SIZE,
+ IFLA_TSO_MAX_SEGS,
__IFLA_MAX
};
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 91a6fe4e02c0..6a184d260c7f 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -445,7 +445,13 @@ struct kvm_run {
#define KVM_SYSTEM_EVENT_RESET 2
#define KVM_SYSTEM_EVENT_CRASH 3
__u32 type;
- __u64 flags;
+ __u32 ndata;
+ union {
+#ifndef __KERNEL__
+ __u64 flags;
+#endif
+ __u64 data[16];
+ };
} system_event;
/* KVM_EXIT_S390_STSI */
struct {
@@ -1144,6 +1150,8 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_S390_MEM_OP_EXTENSION 211
#define KVM_CAP_PMU_CAPABILITY 212
#define KVM_CAP_DISABLE_QUIRKS2 213
+/* #define KVM_CAP_VM_TSC_CONTROL 214 */
+#define KVM_CAP_SYSTEM_EVENT_DATA 215
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 44e1f8a44087..d5289fa58a4f 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -311,6 +311,7 @@ err_out:
/* BUG_ON due to failure in allocation of orig_mask/mask */
BUG_ON(-1);
+ return NULL;
}
static cpu_set_t *bind_to_node(int target_node)
@@ -364,6 +365,7 @@ err_out:
/* BUG_ON due to failure in allocation of orig_mask/mask */
BUG_ON(-1);
+ return NULL;
}
static void bind_to_cpumask(cpu_set_t *mask)
diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh
index 6de53b7ef5ff..e4cb4f1806ff 100755
--- a/tools/perf/tests/shell/test_arm_coresight.sh
+++ b/tools/perf/tests/shell/test_arm_coresight.sh
@@ -29,7 +29,6 @@ cleanup_files()
rm -f ${file}
rm -f "${perfdata}.old"
trap - exit term int
- kill -2 $$
exit $glb_err
}
diff --git a/tools/testing/selftests/drivers/net/netdevsim/hw_stats_l3.sh b/tools/testing/selftests/drivers/net/netdevsim/hw_stats_l3.sh
index fe1898402987..cba5ac08426b 100755
--- a/tools/testing/selftests/drivers/net/netdevsim/hw_stats_l3.sh
+++ b/tools/testing/selftests/drivers/net/netdevsim/hw_stats_l3.sh
@@ -319,11 +319,11 @@ counter_test()
((pkts < 10))
check_err $? "$type stats show >= 10 packets after first enablement"
- sleep 2
+ sleep 2.5
local pkts=$(get_hwstat dummy1 l3 rx.packets)
((pkts >= 20))
- check_err $? "$type stats show < 20 packets after 2s passed"
+ check_err $? "$type stats show < 20 packets after 2.5s passed"
$IP stats set dev dummy1 ${type}_stats off
diff --git a/tools/testing/selftests/net/forwarding/Makefile b/tools/testing/selftests/net/forwarding/Makefile
index b5181b5a8e29..8f481218a492 100644
--- a/tools/testing/selftests/net/forwarding/Makefile
+++ b/tools/testing/selftests/net/forwarding/Makefile
@@ -88,7 +88,7 @@ TEST_PROGS = bridge_igmp.sh \
vxlan_bridge_1d_port_8472.sh \
vxlan_bridge_1d.sh \
vxlan_bridge_1q_ipv6.sh \
- vxlan_bridge_1q_port_8472_ipv6.sh
+ vxlan_bridge_1q_port_8472_ipv6.sh \
vxlan_bridge_1q_port_8472.sh \
vxlan_bridge_1q.sh \
vxlan_symmetric_ipv6.sh \
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index d1de1e7702fb..a4406b7a8064 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -1571,6 +1571,33 @@ chk_prio_nr()
[ "${dump_stats}" = 1 ] && dump_stats
}
+chk_subflow_nr()
+{
+ local need_title="$1"
+ local msg="$2"
+ local subflow_nr=$3
+ local cnt1
+ local cnt2
+
+ if [ -n "${need_title}" ]; then
+ printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${msg}"
+ else
+ printf "%-${nr_blank}s %s" " " "${msg}"
+ fi
+
+ cnt1=$(ss -N $ns1 -tOni | grep -c token)
+ cnt2=$(ss -N $ns2 -tOni | grep -c token)
+ if [ "$cnt1" != "$subflow_nr" -o "$cnt2" != "$subflow_nr" ]; then
+ echo "[fail] got $cnt1:$cnt2 subflows expected $subflow_nr"
+ fail_test
+ dump_stats=1
+ else
+ echo "[ ok ]"
+ fi
+
+ [ "${dump_stats}" = 1 ] && ( ss -N $ns1 -tOni ; ss -N $ns1 -tOni | grep token; ip -n $ns1 mptcp endpoint )
+}
+
chk_link_usage()
{
local ns=$1
@@ -2693,6 +2720,7 @@ fastclose_tests()
pedit_action_pkts()
{
tc -n $ns2 -j -s action show action pedit index 100 | \
+ grep "packets" | \
sed 's/.*"packets":\([0-9]\+\),.*/\1/'
}
@@ -2704,6 +2732,16 @@ fail_tests()
chk_join_nr 0 0 0 +1 +0 1 0 1 "$(pedit_action_pkts)"
chk_fail_nr 1 -1 invert
fi
+
+ # multiple subflows
+ if reset_with_fail "MP_FAIL MP_RST" 2; then
+ tc -n $ns2 qdisc add dev ns2eth1 root netem rate 1mbit delay 5
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 1024
+ chk_join_nr 1 1 1 1 0 1 1 0 "$(pedit_action_pkts)"
+ fi
}
userspace_tests()
@@ -2774,7 +2812,7 @@ userspace_tests()
fi
}
-implicit_tests()
+endpoint_tests()
{
# userspace pm type prevents add_addr
if reset "implicit EP"; then
@@ -2796,6 +2834,23 @@ implicit_tests()
$ns2 10.0.2.2 id 1 flags signal
wait
fi
+
+ if reset "delete and re-add"; then
+ pm_nl_set_limits $ns1 1 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 4 0 0 slow &
+
+ wait_mpj $ns2
+ pm_nl_del_endpoint $ns2 2 10.0.2.2
+ sleep 0.5
+ chk_subflow_nr needtitle "after delete" 1
+
+ pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow
+ wait_mpj $ns2
+ chk_subflow_nr "" "after re-add" 2
+ wait
+ fi
}
# [$1: error message]
@@ -2844,7 +2899,7 @@ all_tests_sorted=(
z@fastclose_tests
F@fail_tests
u@userspace_tests
- I@implicit_tests
+ I@endpoint_tests
)
all_tests_args=""
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index 04a49e876a46..5b1ecd00695b 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -57,9 +57,9 @@ CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh "$(CC)" ../x86/trivial_32bit_prog
CAN_BUILD_X86_64 := $(shell ./../x86/check_cc.sh "$(CC)" ../x86/trivial_64bit_program.c)
CAN_BUILD_WITH_NOPIE := $(shell ./../x86/check_cc.sh "$(CC)" ../x86/trivial_program.c -no-pie)
-TARGETS := protection_keys
-BINARIES_32 := $(TARGETS:%=%_32)
-BINARIES_64 := $(TARGETS:%=%_64)
+VMTARGETS := protection_keys
+BINARIES_32 := $(VMTARGETS:%=%_32)
+BINARIES_64 := $(VMTARGETS:%=%_64)
ifeq ($(CAN_BUILD_WITH_NOPIE),1)
CFLAGS += -no-pie
@@ -112,7 +112,7 @@ $(BINARIES_32): CFLAGS += -m32 -mxsave
$(BINARIES_32): LDLIBS += -lrt -ldl -lm
$(BINARIES_32): $(OUTPUT)/%_32: %.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
-$(foreach t,$(TARGETS),$(eval $(call gen-target-rule-32,$(t))))
+$(foreach t,$(VMTARGETS),$(eval $(call gen-target-rule-32,$(t))))
endif
ifeq ($(CAN_BUILD_X86_64),1)
@@ -120,7 +120,7 @@ $(BINARIES_64): CFLAGS += -m64 -mxsave
$(BINARIES_64): LDLIBS += -lrt -ldl
$(BINARIES_64): $(OUTPUT)/%_64: %.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
-$(foreach t,$(TARGETS),$(eval $(call gen-target-rule-64,$(t))))
+$(foreach t,$(VMTARGETS),$(eval $(call gen-target-rule-64,$(t))))
endif
# x86_64 users should be encouraged to install 32-bit libraries